Compare commits

...

402 Commits

Author SHA1 Message Date
Dušan Borovčanin 65c6a4d8f4 NOISSUE - Update mGate version (#3217)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-31 16:21:25 +01:00
Sammy Kerata Oina ec223e7467 NOISSUE - Update dependencies in go.mod and go.sum (#3215)
Signed-off-by: Sammy Oina <sammyoina@gmail.com>
2025-10-31 12:47:47 +01:00
Dušan Borovčanin aa3cc3d7ee NOISSUE - Fix API docs (#3212)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-30 18:16:29 +01:00
Steve Munene 9650dde716 NOISSUE - Update API docs (#3211)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-30 17:37:01 +01:00
Arvindh d02747a56f NOISSUE - Fix mqtt adapter target ws server protcol and update mgate version (#3209)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-10-29 14:30:23 +01:00
Felix Gateru dc0df1c955 SMQ-3137 - Proxy CoAP using mgate (#2222)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-10-24 17:55:02 +02:00
Steve Munene 64b4497ad4 NOISSUE - Increase NGINX client body size (#3204)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-22 15:55:37 +02:00
Dušan Borovčanin 1b26264495 NOISSUE - Fix SSO User metadata update (#3203)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-22 15:32:55 +02:00
Felix Gateru 69366d77cc SMQ-3171 - Add domain ID to channel authorization request (#3179)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-10-22 12:53:37 +02:00
Washington Kigani Kamadi fa8862cbc8 NOISSUE - Add auth_provider field to sdk (#3202)
Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
2025-10-22 12:51:38 +02:00
Dušan Borovčanin 15b8901853 NOISSUE - Fix password reset (#3200)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-21 19:44:41 +02:00
Dušan Borovčanin 9258237cb6 NOISSUE - Add domain field in domains callouts (#3199)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-21 14:31:11 +02:00
Dušan Borovčanin 2adeecd9ec NOISSUE - Update call-home (#3198)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-20 20:44:46 +02:00
Dušan Borovčanin c5eee6d8fd NOISSUE - Update dependencies (#3197)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-20 16:54:01 +02:00
dependabot[bot] 648edbd386 NOISSUE - Bump github.com/nats-io/nats.go from 1.46.1 to 1.47.0 (#3195)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-20 12:45:33 +02:00
dependabot[bot] 35fb296318 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.14.0 to 9.14.1 (#3196)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-20 12:44:21 +02:00
dependabot[bot] a98777b191 NOISSUE - Bump golang from 1.25.1-alpine to 1.25.3-alpine in /docker in the docker-dependency group (#3194)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-20 12:07:32 +02:00
Dušan Borovčanin 3c693a7b41 NOISSUE - Fix key logging (#3193)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-17 15:24:24 +02:00
Dušan Borovčanin c230a24b7d NOISSUE - Use structured requests in callouts (#3191)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-17 13:11:20 +02:00
Steve Munene 42b2a8c166 NOISSUE - Close PATs sql rows (#3190)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-16 16:32:54 +02:00
Dušan Borovčanin 6468ebe749 NOISSUE - Fix Domain creation callout (#3189)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-16 15:38:51 +02:00
b1ackd0t 1adbe1ff24 NOISSUE - Enhance docker-compose and Makefile configurations (#3153)
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-10-15 14:41:16 +02:00
Arvindh 27995cb093 NOISSUE - Add Auth provider in profile view response (#3187)
Signed-off-by: Arvindh <arvindh91@gmail.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Co-authored-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-15 14:17:37 +02:00
dependabot[bot] 5833bafbee NOISSUE - Bump golang.org/x/oauth2 from 0.31.0 to 0.32.0 (#3183)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-15 14:09:44 +02:00
dependabot[bot] 6394908b2c NOISSUE - Bump golang.org/x/crypto from 0.42.0 to 0.43.0 (#3182)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-15 10:27:49 +02:00
dependabot[bot] 0e0598c6d8 NOISSUE - Bump github.com/authzed/spicedb from 1.45.4 to 1.46.0 (#3184)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-15 10:26:21 +02:00
dependabot[bot] 3e400da5ad NOISSUE - Bump google.golang.org/grpc from 1.75.1 to 1.76.0 (#3185)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-15 10:25:56 +02:00
Arvindh 2112281171 NOISSUE - Auto generation username for oauth user during singup (#3178)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-10-09 15:19:46 +02:00
Arvindh 6f40c7fa1e NOISSUE - Handle Domain & Channel Route not available error during creation (#3180)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-10-09 15:06:06 +02:00
Arvindh b0e9e43b9e NOISSUE - Handle user registration errors (#3177)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-10-08 19:56:54 +02:00
Felix Gateru bc7727c275 SMQ-3175 - Fix clearing domain metadata on domain name and tags update (#3176)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-10-08 17:36:03 +02:00
Arvindh 8d1c3c41b5 NOISSUE - Fix OAuth auto verification on register (#3174)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-10-07 18:24:23 +02:00
dependabot[bot] d84df8604f NOISSUE - Bump github.com/authzed/authzed-go from 1.5.1-0.20250909211335-16b58d03994c to 1.6.0 (#3168)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-06 11:04:55 +02:00
dependabot[bot] d4d8bc5351 NOISSUE - Bump google.golang.org/protobuf from 1.36.9 to 1.36.10 (#3167)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-06 10:55:26 +02:00
dependabot[bot] ac9bc9aad6 NOISSUE - Bump github.com/nats-io/nats.go from 1.46.0 to 1.46.1 (#3166)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-06 10:48:52 +02:00
dependabot[bot] 4b83301f69 NOISSUE - Bump peter-evans/repository-dispatch from 3 to 4 in /.github/workflows in the gh-dependency group (#3161)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-02 13:18:19 +02:00
Arvindh b746a8679f NOISSUE - Fixing auto verification unverified users flow (#3163)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-10-02 13:17:32 +02:00
Arvindh e6022542b9 NOISSUE - Auto verify OAuth user during OAuth Callback (#3162)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-10-02 11:14:06 +02:00
Arvindh 6c77e1b738 SMQ-3159 - Return specific error on non-existent user during login (#3160)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-10-01 18:51:50 +02:00
Steve Munene 04774ae972 NOISSUE - Remove empty file (#3157)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-01 11:44:26 +02:00
Steve Munene ae7c93020a SMQ-3028 - Unify SMQ certs with Absmach Certs (#3146)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-01 11:08:33 +02:00
Felix Gateru b031dc08b8 NOISSUE - Group service middleware into single folder (#2472)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-09-26 13:55:00 +02:00
dependabot[bot] 0465ceb7a3 NOISSUE - Bump github.com/nats-io/nats.go from 1.45.0 to 1.46.0 (#3152)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-25 16:47:52 +02:00
dependabot[bot] af424ee2cb NOISSUE - Bump github.com/authzed/spicedb from 1.45.3 to 1.45.4 (#3150)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-21 19:43:31 +03:00
dependabot[bot] 96a15b32dd NOISSUE - Bump github.com/eclipse/paho.mqtt.golang from 1.5.0 to 1.5.1 (#3151)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-21 19:20:37 +03:00
Felix Gateru 61f1e9aca2 MG-314 - Update API docs related for listing entities (#3149)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-09-18 12:18:00 +02:00
Nataly Musilah 29f7063c15 NOISSUE - Fix Groups and Channels Users Listing (#3138)
Signed-off-by: musilah <nataleigh.nk@gmail.com>
2025-09-18 11:28:40 +02:00
Felix Gateru 1f48a73677 SMQ-2945 - Add channels events consumer (#2951)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-09-16 17:23:01 +02:00
Felix Gateru cd9cb9e1d5 SMQ-2944 - Add client events consumer (#2947)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-09-16 17:21:39 +02:00
dependabot[bot] 8d9e92f228 NOISSUE - Bump google.golang.org/protobuf from 1.36.8 to 1.36.9 (#3142)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-15 12:41:24 +02:00
dependabot[bot] ad685c27ad NOISSUE - Bump github.com/redis/go-redis/v9 from 9.13.0 to 9.14.0 (#3141)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-15 12:24:53 +02:00
dependabot[bot] 44485cacec NOISSUE - Bump google.golang.org/grpc from 1.75.0 to 1.75.1 (#3143)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-15 12:24:13 +02:00
Felix Gateru 7fac6ff4c4 SMQ-2801 - Add health check endpoint with client authentication to CoAP adapter (#3139)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-09-15 12:23:36 +02:00
Felix Gateru 1930a0c8f2 SMQ-2801 - Add health check endpoint to WS adapter (#3144)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-09-15 10:33:39 +02:00
Felix Gateru 9eac9366ba SMQ-2801 - Add health check endpoint to HTTP adapter (#3140)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-09-12 12:14:14 +02:00
Felix Gateru ad191c4609 SMQ-2801 - Add health check endpoint for MQTT adapter (#3024)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-09-12 11:37:29 +02:00
dependabot[bot] 1d935f0519 NOISSUE - Bump golang.org/x/crypto from 0.41.0 to 0.42.0 (#3133)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 08:54:25 +02:00
dependabot[bot] bc1ccace4a NOISSUE - Bump github.com/absmach/callhome from 0.14.0 to 0.18.1 (#3134)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 08:53:53 +02:00
dependabot[bot] 89fdb4e6c7 NOISSUE - Bump golang.org/x/oauth2 from 0.30.0 to 0.31.0 (#3135)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 08:52:42 +02:00
dependabot[bot] 44e44639aa NOISSUE - Bump github.com/jackc/pgx/v5 from 5.7.5 to 5.7.6 (#3136)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 08:52:08 +02:00
dependabot[bot] d31c66174e NOISSUE - Bump actions/setup-go from 5 to 6 in /.github/workflows in the gh-dependency group (#3131)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-06 18:05:13 +02:00
dependabot[bot] e6d7a07277 NOISSUE - Bump golang from 1.25.0-alpine to 1.25.1-alpine in /docker in the docker-dependency group (#3127)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-06 18:03:18 +02:00
dependabot[bot] a2ea92a5ba NOISSUE - Bump github.com/prometheus/client_golang from 1.23.0 to 1.23.2 (#3130)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-06 18:01:27 +02:00
dependabot[bot] 3320a716f3 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.12.1 to 9.13.0 (#3128)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-06 18:00:49 +02:00
Felix Gateru a70b838f1c SMQ-2924 - Allow bulk deleting of invitations from repository (#2942)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-09-05 19:26:45 +02:00
Nataly Musilah c50221a042 NOISSUE - Update entity sorting (#3076)
Signed-off-by: Musilah <nataleigh.nk@gmail.com>
Signed-off-by: musilah <nataleigh.nk@gmail.com>
2025-09-05 15:58:03 +02:00
Arvindh 1efa8b5bce NOISSUE - Allow unverified users by default in docker compose (#3124)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-09-05 15:40:47 +02:00
Arvindh e57ad79cd4 SMQ-3093 - User email verification (#3101)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-09-05 15:23:58 +02:00
Sammy Kerata Oina 22616911d2 NOISSUE - Change email body format from plain text to HTML in Send method (#3118)
Signed-off-by: Sammy Oina <sammyoina@gmail.com>
2025-09-04 19:54:01 +02:00
Steve Munene 766bb5519a SMQ-2275 - Update SDK godocs (#3119)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-09-04 11:35:12 +02:00
Steve Munene fbcdef9693 SMQ-3061 - Separate CLI command for Domain and User Invitations (#3117)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-09-03 13:00:23 +02:00
dependabot[bot] 9aacde7c5b NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp from 0.62.0 to 0.63.0 (#3115)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 10:43:14 +02:00
dependabot[bot] cdf26051f6 NOISSUE - Bump github.com/openbao/openbao/api/v2 from 2.3.1 to 2.4.0 (#3112)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 10:30:12 +02:00
dependabot[bot] a9a412e909 NOISSUE - Bump github.com/spf13/cobra from 1.9.1 to 1.10.1 (#3111)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 10:28:43 +02:00
dependabot[bot] 0754fa1126 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc from 0.62.0 to 0.63.0 (#3116)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-03 10:28:20 +02:00
Steve Munene ec75f4eadb SMQ-3062 - Update Domain Invitation Deletion Endpoint (#3110)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-09-02 10:16:49 +02:00
Washington Kigani Kamadi af35396601 NOISSUE - Obtain email host from env (#3098)
Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
2025-09-01 15:21:01 +02:00
dependabot[bot] 6a27594751 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp from 1.37.0 to 1.38.0 (#3105)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-01 14:52:42 +02:00
dependabot[bot] 555d89d358 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace from 1.37.0 to 1.38.0 (#3103)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-01 10:41:50 +02:00
dependabot[bot] c3c9dcf318 NOISSUE - Bump github.com/go-chi/chi/v5 from 5.2.2 to 5.2.3 (#3104)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-01 10:35:19 +02:00
dependabot[bot] 5a75772f62 NOISSUE - Bump go.opentelemetry.io/otel from 1.37.0 to 1.38.0 (#3107)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-01 10:35:01 +02:00
Steve Munene b9ac94f058 SMQ-2495 - Refactor CLI to use entity IDs (#3100)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-09-01 10:22:14 +02:00
Felix Gateru 8ab1f4c408 SMQ-2836 - Skip checking super admin if the role in JWT is not super admin (#3099)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-29 12:09:31 +02:00
Dušan Borovčanin e842bfaab6 NOISSUE - Update Protobufs (#3091)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-26 13:31:08 +02:00
dependabot[bot] 886cd63415 NOISSUE - Bump github.com/stretchr/testify from 1.10.0 to 1.11.0 (#3089)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 12:29:54 +02:00
dependabot[bot] 9cd22910d8 NOISSUE - Bump github.com/dgraph-io/ristretto/v2 from 2.2.0 to 2.3.0 (#3090)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 12:27:28 +02:00
Felix Gateru 906e365adf NOISSUE - Fix clients listing repository tests (#3088)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-26 12:25:57 +02:00
dependabot[bot] 8e7e897906 NOISSUE - Bump github.com/authzed/authzed-go from 1.4.1 to 1.5.0 (#3084)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 00:13:39 +02:00
dependabot[bot] 4b50ef93a2 NOISSUE - Bump actions/checkout from 4 to 5 in /.github/workflows in the gh-dependency group (#3080)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-25 23:54:33 +02:00
dependabot[bot] 73c2d76b58 NOISSUE - Bump google.golang.org/grpc from 1.74.2 to 1.75.0 (#3083)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-25 23:53:02 +02:00
dependabot[bot] 473338527a NOISSUE - Bump google.golang.org/protobuf from 1.36.7 to 1.36.8 (#3082)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-25 23:29:09 +02:00
dependabot[bot] 12d1a0de32 NOISSUE - Bump github.com/authzed/spicedb from 1.45.1 to 1.45.3 (#3085)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-25 23:27:48 +02:00
dependabot[bot] b4e0e89c38 NOISSUE - Bump github.com/nats-io/nats.go from 1.44.0 to 1.45.0 (#3086)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-25 23:20:39 +02:00
dependabot[bot] 6f5e535b30 NOISSUE - Bump golang from 1.24.5-alpine to 1.25.0-alpine in /docker in the docker-dependency group (#3081)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-25 23:19:09 +02:00
Dušan Borovčanin fb1062a98a NOISSUE - Fix linters and Mockery (#3087)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-25 23:15:38 +02:00
dusan c56a5ae577 NOISSUE - Update Go version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-25 18:37:56 +02:00
Dušan Borovčanin a19cd9c97b NOISSUE - Replace interface{} with any (#3079)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-25 18:06:41 +02:00
Felix Gateru 0e1a090f16 SMQ-3070 - Fix property based tests (#3078)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-25 16:17:19 +02:00
dependabot[bot] ef712443e1 NOISSUE - Bump github.com/go-viper/mapstructure/v2 from 2.3.0 to 2.4.0 (#3077)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-25 13:24:09 +02:00
Smith Jilks 248b708909 NOISSUE - Update callouts client tls config (#3068)
Signed-off-by: Jilks Smith <smithjilks@gmail.com>
2025-08-21 16:44:11 +02:00
Felix Gateru c63c936b36 SMQ-3073 - Enable user messaging through WS and HTTP protocols (#3075)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-21 16:10:34 +02:00
Felix Gateru 4927333691 NOISSUE - Update SMQ version in docs (#3072)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-20 15:56:54 +02:00
dependabot[bot] 5acc8f96a6 NOISSUE - Bump golang.org/x/crypto from 0.40.0 to 0.41.0 (#3059)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 18:28:33 +02:00
dependabot[bot] 9d91740063 NOISSUE - Bump google.golang.org/protobuf from 1.36.6 to 1.36.7 (#3060)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 14:06:20 +02:00
dependabot[bot] 1951f206cb NOISSUE - Bump github.com/docker/docker from 27.1.1+incompatible to 28.0.0+incompatible (#3067)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 14:00:08 +02:00
dependabot[bot] 441feb8578 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.11.0 to 9.12.1 (#3058)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 13:57:48 +02:00
dependabot[bot] 7d11f16988 NOISSUE - Bump github.com/absmach/certs from 0.0.0-20250602111612-89538302ad6a to 0.17.0 (#3057)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 13:56:36 +02:00
Nataly Musilah 2e3f52fdbf NOISSUE - Allow sorting (#3052)
Signed-off-by: Musilah <nataleigh.nk@gmail.com>
2025-08-18 14:54:26 +02:00
Felix Gateru b942a42271 SMQ-3053 - Fix listing subgroups for users with subgroup related actions (#3066)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-18 09:24:23 +02:00
Steve Munene 0178594c25 SMQ-3056 - Fix exposed secret in MQTT (#3065)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-08-18 09:23:01 +02:00
Steve Munene 3dbd617ed0 SMQ-3050 - Fix PAT redis connection (#3051)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-08-13 14:50:20 +02:00
Felix Gateru 8188da16b3 NOISSUE - Update removal of view invitation endpoint in sdk and cli (#3055)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-13 14:48:12 +02:00
Smith Jilks bc7b988098 NOISSUE - Add ability to handle both tls cert file and raw cert data (#2871)
Signed-off-by: Jilks Smith <smithjilks@gmail.com>
2025-08-08 15:48:36 +02:00
Felix Gateru a0b3970ad6 SMQ-3032 - Remove view invitations endpoint (#3042)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-07 20:31:15 +02:00
Felix Gateru 0f20663cfb SMQ-2704 - Update listing of group hierarchy (#2710)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-07 11:53:23 +02:00
Felix Gateru 4dc98763a6 SMQ-3044 - Fix listing channel logs with operation query parameter (#3043)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-05 20:55:09 +02:00
Filip Bugarski 230be1d13b NOISSUE - Fix typos (#2927)
Signed-off-by: fbugarski <filipbugarski@gmail.com>
2025-08-03 15:56:45 +02:00
Arvindh 99493d86ff NOISSUE - Fix callout test (#3041)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-08-01 14:28:49 +02:00
Arvindh 4ffb1fe422 NOISSUE - Handle callout error (#3039)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-08-01 13:53:21 +02:00
Washington Kigani Kamadi f4417ecb78 NOISSUE - List domain invitations on SDK (#3038)
Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
2025-08-01 09:48:32 +02:00
Dušan Borovčanin 9b77130f6e SMQ-2866 - MQTT auth fails with identical secrets across different domains (#3030)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-31 14:55:37 +02:00
dependabot[bot] 71ea84c3ec NOISSUE - Bump github.com/prometheus/client_golang from 1.22.0 to 1.23.0 (#3033)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 13:04:23 +02:00
dependabot[bot] 36c138688d NOISSUE - Bump github.com/nats-io/nats.go from 1.43.0 to 1.44.0 (#3034)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 13:00:20 +02:00
Washington Kigani Kamadi 86afe1736f NOISSUE - Add domain name to invitation (#3031)
Signed-off-by: WashingtonKK <washingtonkigan@gmail.com>
2025-07-30 18:32:49 +02:00
Steve Munene 8e70e1113e SMQ-3201 - Replace Vault with openbao (#3019)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-07-28 12:03:50 +02:00
b1ackd0t a379d11035 NOISSUE - Fix mTLS setup (#3029)
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-07-23 12:58:15 +02:00
dependabot[bot] 45a5c42ea4 NOISSUE - Bump google.golang.org/grpc from 1.73.0 to 1.74.2 (#3027)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 10:08:17 +02:00
Felix Gateru 99a55a6e24 SMQ-2801 - Add health check endpoint for CoAP adapter (#3022)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-21 18:14:55 +02:00
Felix Gateru 6e404caa32 NOISSUE - Move codecov yaml file (#3020)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-17 11:18:01 +02:00
Felix Gateru 898048cb8b SMQ-2967- Rename RetrieveByRoute method to RetrieveIDByRoute (#2972)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-15 12:05:39 +02:00
Felix Gateru 0794c2828e SMQ-2966 - Rename domains RetrieveEntity to RetrieveStatus (#2973)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-15 11:24:41 +02:00
dependabot[bot] 7be4ec6890 NOISSUE - Bump github.com/absmach/senml from 1.0.7 to 1.0.8 (#3018)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-15 10:58:33 +02:00
Felix Gateru 5669e8a76e SMQ-2977 - Add cache for message topic caching (#3000)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-15 10:46:45 +02:00
Steve Munene d4dc7ffe35 SMQ-2873 - Switch to TIMESTAMPZ in Postgres (#3015)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-07-14 23:35:47 +02:00
Felix Gateru b6080bc42b SMQ-3016 - Fix false positive http logging (#3017)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-14 17:25:42 +02:00
Felix Gateru 0dea465fb3 SMQ-2958 - Fix failing reset password flow (#2970)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-14 16:37:09 +02:00
dependabot[bot] 879225f7a8 NOISSUE - Bump golang.org/x/crypto from 0.39.0 to 0.40.0 (#3013)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-14 10:03:08 +02:00
dependabot[bot] f8a7a75486 NOISSUE - Bump github.com/authzed/spicedb from 1.44.4 to 1.45.1 (#3014)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-14 09:05:34 +02:00
Felix Gateru fb0b188d4e SMQ-2985 - Use coap mux.Handler instead of coap mux.HandlerFunc (#2992)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-10 17:57:22 +02:00
Steve Munene 376bc8b9c4 SMQ-2840 - Retrieve entity total with filter options (#2961)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-07-10 17:36:31 +02:00
JeffMboya da319a1aa9 NOISSUE - Fix db connection leaks (#3009)
Signed-off-by: JeffMboya <jangina.mboya@gmail.com>
2025-07-10 13:26:37 +02:00
Felix Gateru 2ab3db79e5 SMQ-2997 - Use nlevel to filter root groups (#3005)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-10 12:46:31 +02:00
Dusan Borovcanin 33e8d4f47e NOISSUE - Update Go version
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-10 12:27:48 +02:00
dependabot[bot] 902e85e648 NOISSUE - Bump golang from 1.24.4-alpine to 1.24.5-alpine in /docker in the docker-dependency group (#3006)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 12:25:15 +02:00
dependabot[bot] afb28667c4 NOISSUE - Bump golang.org/x/sync from 0.15.0 to 0.16.0 (#3008)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 12:23:24 +02:00
dependabot[bot] 26feb34f8d NOISSUE - Bump github.com/plgd-dev/go-coap/v3 from 3.3.6 to 3.4.0 (#3007)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 12:15:45 +02:00
Steve Munene bdfdb67998 SMQ-3001 - Fix issue token return error (#3004)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-07-09 20:39:26 +02:00
Felix Gateru 1c0400d3a5 SMQ-2260 - Log full errors in logging middleware (#3003)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-09 15:21:16 +02:00
Dusan Borovcanin fa5b6b86c6 NOISSUE - Fix Swagger docs dir
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-07 10:42:44 +02:00
Dusan Borovcanin 16f1b411ec NOISSUE - Update Swagger UI
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-07 10:23:17 +02:00
Dušan Borovčanin be66701b15 NOISSUE - Update nullable handling (#2999)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-04 17:34:31 +02:00
Felix Gateru 0a18a580eb SMQ-2865 - Fix listing indirect groups and group related listing of channels and clients (#2976)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-04 17:33:58 +02:00
Dušan Borovčanin a0044c51be NOISSUE - Fix Domain mocks (#2998)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-03 18:18:50 +02:00
Steve Munene 788d8334f7 SMQ-2743 - Update group description to nullable string (#2968)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-07-03 18:15:31 +02:00
Felix Gateru 7ecdd7ebe3 SMQ-2971 - Bump mockery version to 3.5.0 (#2991)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-03 15:14:14 +02:00
dependabot[bot] dda01ff4a1 NOISSUE - Bump schemathesis/action from 2.0.1 to 2.1.0 in /.github/workflows in the gh-dependency group (#2993)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 15:50:10 +02:00
Felix Gateru 5d04de4ffa SMQ-2719 - Update list domain invitations endpoint (#2965)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-01 19:03:33 +02:00
dependabot[bot] f6e8db4c09 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp from 1.36.0 to 1.37.0 (#2989)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 16:20:05 +02:00
dependabot[bot] 0f9ae05615 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.10.0 to 9.11.0 (#2988)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 16:12:29 +02:00
dependabot[bot] bcba9e962e NOISSUE - Bump github.com/authzed/authzed-go from 1.4.0 to 1.4.1 (#2990)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 16:10:49 +02:00
unwynd 191f8a1e0f SMQ-2862 - Update OpenAPI spec for Journal service (#2938)
Signed-off-by: Abdullah Elmarghany <abdullah@elmarghany.com>
2025-07-01 15:04:52 +02:00
Felix Gateru 0d1aafcbbf SMQ-2956 - Add routes resolver to abstract topic resolution logic (#2960)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-01 15:04:01 +02:00
Steve Munene 9a194a86df SMQ-2987 - Fix view domain roles using roleID (#2986)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-30 19:09:21 +02:00
dependabot[bot] 668013cbad NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp from 0.61.0 to 0.62.0 (#2982)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 10:08:15 +02:00
dependabot[bot] d83f0b8559 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace from 1.36.0 to 1.37.0 (#2980)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 10:04:32 +02:00
dependabot[bot] c198e8093b NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc from 0.61.0 to 0.62.0 (#2983)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 10:01:08 +02:00
dependabot[bot] 12a562284e NOISSUE - Bump go.opentelemetry.io/otel/sdk from 1.36.0 to 1.37.0 (#2984)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 09:48:25 +02:00
dependabot[bot] 54c1ff0587 NOISSUE - Bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0 (#2979)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-28 12:58:54 +02:00
Steve Munene d9cf3851a1 SMQ-2974 - Fix listing entities from different domains (#2975)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-26 14:12:57 +02:00
Felix Gateru 9abdf39fd6 SMQ-2962 - Add constraints to username creation (#2963)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-06-24 13:55:02 +02:00
Felix Gateru d8e895970c NOISSUE - Fix listing groups audit logs (#2940)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-06-23 11:58:28 +02:00
dependabot[bot] f7f399a5a5 NOISSUE - Bump schemathesis/action from 2.0.0 to 2.0.1 in /.github/workflows in the gh-dependency group (#2959)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-23 10:17:23 +02:00
dependabot[bot] 3a1b9ce20b NOISSUE - Bump github.com/go-chi/chi/v5 from 5.2.1 to 5.2.2 (#2957)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-23 09:41:11 +02:00
JeffMboya 8d04e7adbe SMQ-2905 - Add repo dispatch to trigger stage deployment (#2906)
Signed-off-by: JeffMboya <jangina.mboya@gmail.com>
2025-06-20 16:11:09 +02:00
Felix Gateru 707ca54ef9 NOISSUE - Bump Schemathesis action from v1 to v2.0.0 (#2954)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-06-20 15:57:45 +02:00
Felix Gateru ca93b8865a SMQ-2702 - Add cache for channel and domain routes (#2914)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-06-20 14:10:20 +02:00
Smith Jilks 86dd4ede3a NOISSUE - Update issue token in oauth2CallbackHandler (#2955)
Signed-off-by: Jilks Smith <smithjilks@gmail.com>
2025-06-20 09:58:21 +02:00
Felix Gateru 5b7b759131 SMQ-2761 - Support domain and channel routes in message topic (#2775)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-06-20 09:57:36 +02:00
dependabot[bot] 2aa247b3c3 NOISSUE - Bump github.com/authzed/spicedb from 1.44.3 to 1.44.4 (#2948)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-19 16:41:07 +02:00
Dusan Borovcanin ec126a5976 NOISSUE - Fix certs compose
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-18 18:40:06 +02:00
Arvindh c8814237cf NOISSUE - Increase NATS message payload size (#2950)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-06-17 12:18:37 +02:00
Arvindh e98b6576f1 NOISSUE - Add Message Details to NATS Subscriber Handler Logs (#2941)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-06-16 11:55:52 +02:00
dependabot[bot] c429b1d5ff NOISSUE - Bump github.com/authzed/spicedb from 1.44.2 to 1.44.3 (#2943)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-16 09:56:15 +02:00
dorcaslitunya 09de0cf2f5 SMQ-2909 Allow different formats for user profile from different oauth providers (#2923)
Signed-off-by: Dorcas Litunya <anonolitunya@gmail.com>
Co-authored-by: Dorcas Litunya <dolitunya@microsoft.com>
2025-06-12 12:05:48 +03:00
Arvindh a01d933218 NOISSUE - Add Message error type (#2939)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-06-12 12:02:53 +03:00
JeffMboya d8b7af424e SMQ-2739 - Prevent removing of all users from Built in admin role (#2835)
Signed-off-by: JeffMboya <jangina.mboya@gmail.com>
2025-06-10 10:54:27 +03:00
Felix Gateru 798ed3a2dd NOISSUE - Update mGate version (#2925)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-06-09 19:39:28 +02:00
Dušan Borovčanin d3c9e0bbcd NOISSUE - Add ACK type for message broker handler (#2928)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-09 12:33:08 +02:00
Dusan Borovcanin b69947fc57 NOISSUE - Update Go version
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-09 11:10:17 +02:00
dependabot[bot] e4553f27d1 NOISSUE - Bump golang from 1.24.3-alpine to 1.24.4-alpine in /docker in the docker-dependency group (#2931)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 11:01:37 +02:00
dependabot[bot] cf68a07b00 NOISSUE - Bump golang.org/x/crypto from 0.38.0 to 0.39.0 (#2933)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 10:49:34 +02:00
dependabot[bot] c691fb779a NOISSUE - Bump google.golang.org/grpc from 1.72.2 to 1.73.0 (#2934)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 10:36:24 +02:00
dependabot[bot] a93fccc234 NOISSUE - Bump github.com/hashicorp/vault/api/auth/approle from 0.9.0 to 0.10.0 (#2935)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 10:35:31 +02:00
Felix Gateru 4bea349b04 NOISSUE - Add request ID to role based events (#2890)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-06-09 10:17:47 +02:00
dependabot[bot] ab41689a9b NOISSUE - Bump github.com/redis/go-redis/v9 from 9.9.0 to 9.10.0 (#2936)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 09:58:58 +02:00
dependabot[bot] 921e5111b5 NOISSUE - Bump github.com/authzed/spicedb from 1.44.0 to 1.44.2 (#2929)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-07 17:04:50 +02:00
Arvindh 21c7b1019e SMQ-2888 - Change internal message topic format (#2889)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-06-05 09:48:56 +02:00
Dušan Borovčanin d64a74b1be NOISSUE - Update Go versions in mod.go and Dockerfile (#2922)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-04 14:30:07 +02:00
Steve Munene 343a771c4f SMQ-2893 - Add callout to roles (#2907)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-03 20:01:44 +02:00
dependabot[bot] 5e96516bf6 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.8.0 to 9.9.0 (#2916)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 11:58:25 +02:00
Arvindh 582b764679 NOISSUE - Fix clients and channels listing (#2913)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-05-29 15:54:48 +02:00
Arvindh 56528ee68a NOISSUE - Fix clients and channels listing (#2912)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-05-29 14:58:11 +02:00
dependabot[bot] 8856a26869 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp from 1.35.0 to 1.36.0 (#2903)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 19:55:23 +02:00
dependabot[bot] b2eb51c155 NOISSUE - Bump google.golang.org/grpc from 1.72.1 to 1.72.2 (#2904)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 19:52:11 +02:00
dependabot[bot] a95d1bb672 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace from 1.35.0 to 1.36.0 (#2901)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 14:38:21 +02:00
dependabot[bot] 5b572cd5fc NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc from 0.60.0 to 0.61.0 (#2902)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 14:36:35 +02:00
dependabot[bot] 8fce6fc8d4 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp from 0.60.0 to 0.61.0 (#2900)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 13:38:17 +02:00
Nin Tran d2eabd1836 SMQ-2885 - Fix PKI: load env file early and allow any CN in server cert role (#2886)
Signed-off-by: Nin Tran <nin.tran52@gmail.com>
2025-05-26 10:46:34 +02:00
dependabot[bot] 8c3f621e21 NOISSUE - Bump go.opentelemetry.io/otel from 1.35.0 to 1.36.0 (#2899)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 10:40:31 +02:00
dependabot[bot] 0275c8a5c4 NOISSUE - Bump github.com/oklog/ulid/v2 from 2.1.0 to 2.1.1 (#2898)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 10:29:51 +02:00
Arvindh 0dd25d7140 NOISSUE - Remove .env file trailing whitespace (#2895)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-05-23 15:20:14 +02:00
Steve Munene 079749b3e8 NOISSUE - Fix callout tests (#2896)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-05-23 15:05:21 +02:00
Felix Gateru c0fd0f410f SMQ-2785 - Disable deleting a confirmed or rejected invitation by non invitee user (#2805)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-05-22 18:45:29 +02:00
Steve Munene 58753f60d8 SMQ-2804 - Move Callouts from Auth Service to pkg/authz (#2823)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-05-22 16:08:45 +02:00
Felix Gateru 04f6117e36 SMQ-2761 - Add route field to channels (#2772)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-05-21 18:53:40 +02:00
Dušan Borovčanin 7f4633a3d1 NOISSUE - Add Nullable type for optional values handling (#2877)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-20 18:45:24 +02:00
Felix Gateru d6c260b803 SMQ-2874 - Allow empty update for user profile picture, tags and metadata (#2876)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-05-20 10:29:24 +02:00
dependabot[bot] 2dba6e644f NOISSUE - Bump github.com/authzed/spicedb from 1.43.0 to 1.44.0 (#2883)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-20 09:26:47 +02:00
Felix Gateru a7d2acb591 SMQ-2863 - Fix listing child group's clients and channels with domain access type (#2872)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-05-19 17:10:54 +02:00
Felix Gateru 2b5a670bef SMQ-2842 - Fix client telemetry handling in journal service (#2864)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-05-19 16:50:43 +02:00
dependabot[bot] 16eff6bebb NOISSUE - Bump google.golang.org/grpc from 1.72.0 to 1.72.1 (#2879)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 14:00:38 +02:00
dependabot[bot] c7c224b5f1 NOISSUE - Bump github.com/jackc/pgx/v5 from 5.7.4 to 5.7.5 (#2878)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 13:59:35 +02:00
Steve Munene 86a8f49e82 SMQ-2856 - Add tags to groups (#2860)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-05-16 20:09:16 +02:00
Dušan Borovčanin 9a9e22fbce SMQ-2869 - Switch to UTC time on backends (#2870)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-15 12:01:34 +02:00
Felix Gateru d7d059767b SMQ-2435 - Allow resending rejected invitation (#2868)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-05-14 15:09:13 +02:00
Steve Munene 3b38863b61 SMQ-2841 - List clients and channels with no parent group (#2857)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-05-13 12:20:35 +02:00
Felix Gateru c092e4c888 SMQ-2842 - Update journal service to handle roles events (#2858)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-05-09 15:07:54 +02:00
dependabot[bot] 17a884f7e9 NOISSUE - Bump golang.org/x/oauth2 from 0.29.0 to 0.30.0 (#2852)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 09:38:59 +02:00
dependabot[bot] 920d775965 NOISSUE - Bump golang.org/x/sync from 0.13.0 to 0.14.0 (#2853)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dušan Borovčanin <dusan.borovcanin@abstractmachines.fr>
2025-05-09 09:34:56 +02:00
dependabot[bot] 7a3c598fb9 NOISSUE - Bump golang.org/x/crypto from 0.37.0 to 0.38.0 (#2854)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-09 09:34:26 +02:00
Nin Tran 8b185cf48c SMQ-2845 - fix: mark supermq-base-net as external in addons to prevent recreate conflicts (#2846)
Signed-off-by: Nin Tran <nin.tran52@gmail.com>
2025-05-05 13:43:05 +02:00
dependabot[bot] 0c7ec7c197 NOISSUE - Bump golangci/golangci-lint-action from 7 to 8 in /.github/workflows in the gh-dependency group (#2849)
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:42:06 +02:00
dependabot[bot] 7b13473af8 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.7.3 to 9.8.0 (#2843)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 13:34:35 +02:00
dependabot[bot] b586d988e6 NOISSUE - Bump github.com/lestrrat-go/jwx/v2 from 2.1.5 to 2.1.6 (#2844)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 13:33:28 +02:00
Nin Tran 16ac66c35f SMQ-2847 - Fix vault approle script missing template reference (#2848)
Signed-off-by: Nin Tran <nin.tran52@gmail.com>
2025-05-05 13:33:01 +02:00
dependabot[bot] ecf78a36ba NOISSUE - Bump github.com/authzed/spicedb from 1.42.1 to 1.43.0 (#2850)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 13:16:48 +02:00
dependabot[bot] 39bb9f5240 NOISSUE - Bump github.com/nats-io/nats.go from 1.41.2 to 1.42.0 (#2851)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-05 13:11:09 +02:00
Nin Tran f76332ef71 SMQ-2838 - Mark supermq-base-net as external in addons docker-compose (#2839)
Signed-off-by: Nin Tran <nin.tran52@gmail.com>
2025-04-30 11:51:59 +02:00
Nin Tran ed367fb1e5 SMQ-2832 - Fix make sed -i compatible with both macOS and Linux (#2833)
Signed-off-by: Nin Tran <nin.tran52@gmail.com>
2025-04-27 17:20:20 +02:00
Nin Tran b04fb5cd97 SMQ-2831 - Fix Makefile '@unset' incompatibility on macOS (#2834)
Signed-off-by: Nin Tran <nin.tran52@gmail.com>
2025-04-27 17:13:51 +02:00
Arvindh 5ea3cbd014 NOISSUE - Update mGate version in http and ws adapters (#2825)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-04-25 14:06:37 +02:00
dependabot[bot] cc9fc70d6d NOISSUE - Bump github.com/authzed/authzed-go from 1.3.1-0.20250320210445-0cde0d8c71e2 to 1.4.0 (#2827)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-25 10:38:29 +02:00
dependabot[bot] 8aa5668a73 NOISSUE - Bump github.com/nats-io/nats.go from 1.41.1 to 1.41.2 (#2826)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-25 10:32:14 +02:00
dependabot[bot] bd9e0c9b5a NOISSUE - Bump github.com/rubenv/sql-migrate from 1.7.1 to 1.8.0 (#2829)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-25 10:27:07 +02:00
dependabot[bot] f79cce34fa NOISSUE - Bump github.com/lestrrat-go/jwx/v2 from 2.1.4 to 2.1.5 (#2828)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-25 10:09:55 +02:00
dependabot[bot] fc02c26a84 NOISSUE - Bump google.golang.org/grpc from 1.71.1 to 1.72.0 (#2830)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-25 10:03:53 +02:00
dependabot[bot] c14bb6e18a NOISSUE - Bump golang.org/x/net from 0.37.0 to 0.38.0 (#2824)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 20:43:58 +02:00
dependabot[bot] 62f4599140 NOISSUE - Bump github.com/nats-io/nats.go from 1.41.0 to 1.41.1 (#2821)
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:28 +02:00
dependabot[bot] 56fa8aee84 NOISSUE - Bump github.com/prometheus/client_golang from 1.21.1 to 1.22.0 (#2822)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 10:03:47 +02:00
Steve Munene 6d7100b8ec NOISSUE - Remove name constrains (#2818)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-04-14 10:14:25 +02:00
b1ackd0t 602025b48b NOISSUE - Pass Logger For Messaging (#2819)
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-04-11 17:58:30 +02:00
Dušan Borovčanin 0e571d1905 NOISSUE - Fix build tags (#2817)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-11 15:28:29 +02:00
Arvindh 757ad31f92 NOISSUE - Update broker options (#2816)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-04-11 14:04:14 +02:00
Dušan Borovčanin 01f20a29d2 NOISSUE - Update messaging SDK and CLI (#2815)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-11 12:31:50 +02:00
Dušan Borovčanin 5fd1d9b431 NOISSUE - Update SDK message order (#2814)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-11 11:23:34 +02:00
Felix Gateru 6151be72ce SMQ-2706 - Add domain id to message topic (#2765)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-04-11 09:11:39 +02:00
Felix Gateru 299cee7771 SMQ-2609 - Enable superadmin to perform actions over entities (#2688)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-04-10 16:55:05 +02:00
Dušan Borovčanin a01d2571de NOISSUE - Enable empty Transformers (#2810)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-10 15:54:42 +02:00
Steve Munene 1c3ffba300 SMQ-2807 - Fix retrieve query (#2809)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-04-10 15:24:44 +02:00
Arvindh ba9d65898f NOISSUE - Fix Domains invitations SDK test (#2808)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-04-10 14:26:32 +02:00
Arvindh 814f19390d NOISSUE - Fix domain invitation request and accept (#2806)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-04-09 23:18:47 +02:00
dependabot[bot] af8caa4cc8 NOISSUE - Bump google.golang.org/grpc from 1.71.0 to 1.71.1 (#2797)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 10:52:22 +02:00
dependabot[bot] ff55a7625a NOISSUE - Bump golang.org/x/crypto from 0.36.0 to 0.37.0 (#2796)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 10:42:10 +02:00
dependabot[bot] 8e5daf735d NOISSUE - Bump golang.org/x/oauth2 from 0.28.0 to 0.29.0 (#2798)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 10:24:52 +02:00
dependabot[bot] f2006ae97a NOISSUE - Bump github.com/ory/dockertest/v3 from 3.11.0 to 3.12.0 (#2791)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 11:40:07 +02:00
dependabot[bot] efb392f77b NOISSUE - Bump github.com/authzed/spicedb from 1.41.0 to 1.42.1 (#2792)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 11:34:20 +02:00
dependabot[bot] 739730efe5 NOISSUE - Bump github.com/nats-io/nats.go from 1.40.1 to 1.41.0 (#2793)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 11:30:34 +02:00
dependabot[bot] 05e72a5932 NOISSUE - Bump golang.org/x/sync from 0.12.0 to 0.13.0 (#2794)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 11:26:31 +02:00
dependabot[bot] a1e4b51d55 NOISSUE - Bump github.com/absmach/senml from 1.0.6 to 1.0.7 (#2795)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 08:30:53 +02:00
Dusan Borovcanin 006a1fb0f4 NOISSUE - Fix Makefile user repo sed expression
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-04 19:37:26 +02:00
Dušan Borovčanin e14eee0ac5 NOISSUE - Update Protoc and plugins (#2789)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-04 14:36:25 +02:00
Felix Gateru 49fd8448c0 SMQ-2703 - Shorten channel and message prefix in message topics (#2787)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-04-04 09:39:33 +02:00
Felix Gateru b79fdb1534 SMQ-2760 - Rename domain alias to route (#2776)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-04-02 17:40:04 +02:00
Felix Gateru 3931ecabdb SMQ-2740 - Create events streams per service per action type (#2744)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-04-02 17:14:03 +02:00
Steve Munene 7a3a55d399 NOISSUE - Fix callback (#2788)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-04-02 15:56:32 +02:00
Sammy Kerata Oina 340098cec3 NOISSUE - Pass context on SDK to allow distributed tracing (#2783)
Signed-off-by: Sammy Oina <sammyoina@gmail.com>
2025-04-01 23:54:41 +02:00
dependabot[bot] 12b41e3ab0 NOISSUE - Bump github.com/nats-io/nats.go from 1.40.0 to 1.40.1 (#2778)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 22:09:01 +02:00
dependabot[bot] ce570be40e NOISSUE - Bump github.com/jackc/pgx/v5 from 5.7.3 to 5.7.4 (#2779)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 22:07:32 +02:00
Dusan Borovcanin 5e77512009 NOISSUE - Fix go.mod formatting broken by Dependabot
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 22:02:08 +02:00
dependabot[bot] 321e38590c NOISSUE - Bump github.com/gofrs/uuid/v5 from 5.3.1 to 5.3.2 (#2781)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 21:56:03 +02:00
Dušan Borovčanin 7ae2f7de00 NOISSUE - Update GolangCI linter (#2786)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 21:47:23 +02:00
Dusan Borovcanin 056dd34f9b NOISSUE - Fix actions versions
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 21:13:36 +02:00
Dusan Borovcanin 623b9910d5 NOISSUE - Update Go version
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 21:09:14 +02:00
Felix Gateru 6011cad546 NOISSUE - Update Mockery version and config (#2784)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-04-01 20:56:07 +02:00
Dušan Borovčanin e56b86823e NOISSUE - Rename YAML files extension (#2782)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-03-31 10:51:43 +02:00
dependabot[bot] 878860d249 NOISSUE - Bump google.golang.org/protobuf from 1.36.5 to 1.36.6 (#2770)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 15:04:12 +01:00
dependabot[bot] 3ff3469455 NOISSUE - Bump github.com/nats-io/nats.go from 1.39.1 to 1.40.0 (#2771)
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:47 +01:00
dependabot[bot] cca5e27de7 NOISSUE - Bump github.com/jackc/pgx/v5 from 5.7.2 to 5.7.3 (#2769)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 08:31:44 +01:00
dependabot[bot] 7e1b53bf3e NOISSUE - Bump github.com/redis/go-redis/v9 from 9.7.1 to 9.7.3 (#2768)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 10:21:03 +01:00
Steve Munene ddb3f9ba6d SMQ-2758 - Add option Auth to call webhook for only for certain authz (#2763)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-03-20 23:10:32 +01:00
Felix Gateru 3b675a7ab3 SMQ-2703 - Shorten channel and message prefix in message topics (#2764)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-03-20 22:29:15 +01:00
Steve Munene f6b3938f96 SMQ-2718 - Add actions on view entities response in groups (#2750)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-03-20 12:04:39 +01:00
Steve Munene b0493e03af SMQ-2718 - Add actions on view entities response in channels (#2748)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Co-authored-by: Dušan Borovčanin <dusan.borovcanin@abstractmachines.fr>
2025-03-18 13:17:24 +01:00
Steve Munene 1ad754d933 SMQ-2742 - Add entity role check for optional members when adding role (#2762)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-03-18 13:03:09 +01:00
Steve Munene 001c8255eb SMQ-2718 - Add actions on view entities response in domains (#2749)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Dušan Borovčanin <dusan.borovcanin@abstractmachines.fr>
2025-03-18 12:36:24 +01:00
Steve Munene 1e4341a6ec SMQ-2751 - Add search to PATs (#2753)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-03-14 10:06:03 +01:00
Steve Munene 2bee2efae5 SMQ-2718 - Add actions on view entities response in clients (#2746)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Arvindh <arvindh91@gmail.com>
2025-03-12 13:54:36 +01:00
Ian Ngethe Muchiri 065e764387 NOISSUE - Update changes to domains and channels (#2752)
Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-03-12 13:31:03 +01:00
Sammy Kerata Oina e7032a6313 NOISSUE - Add default members list base query for role management (#2747)
Signed-off-by: Sammy Oina <sammyoina@gmail.com>
2025-03-06 14:15:24 +01:00
b1ackd0t b23a8c20eb NOISSUE - Fix Websocket Adapter (#2700)
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-03-06 11:23:56 +01:00
dependabot[bot] 5cc3c1b4fa NOISSUE - Bump github.com/authzed/spicedb from 1.40.1 to 1.41.0 (#2745)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-04 19:51:11 +01:00
b1ackd0t 88f7172fb4 SMQ-2724 - Add Auth Callout (#2731)
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-03-03 19:29:31 +01:00
Steve Munene fd76a03257 SMQ-2735 - Add PATs README and API docs (#2737)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-03-03 11:51:41 +01:00
dependabot[bot] adf94adc7b NOISSUE - Bump github.com/lestrrat-go/jwx/v2 from 2.1.3 to 2.1.4 (#2741)
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:27 +01:00
Steve Munene 98bc206169 SMQ-2670 - Fix Unauthorized User IDs can be added to domain entity role members (#2684)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-02-28 14:06:59 +01:00
Steve Munene 17b5224090 SMQ-2604 - Change PAT repo implementation (#2680)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Arvindh <arvindh91@gmail.com>
2025-02-27 15:38:34 +01:00
b1ackd0t 56829c15d8 NOISSUE - Use RabbitMQ as MQTT broker (#2695)
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-02-26 09:45:59 +01:00
dependabot[bot] df0f9068d6 NOISSUE - Bump golang.org/x/oauth2 from 0.26.0 to 0.27.0 (#2732)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 19:29:25 +01:00
Arvindh de05aa7f88 NOISSUE - Fix Invitations test (#2723)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-02-25 19:14:49 +01:00
dependabot[bot] 9997d0c77f NOISSUE - Bump golang.org/x/crypto from 0.34.0 to 0.35.0 (#2733)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 15:31:34 +01:00
dependabot[bot] d4c8383266 NOISSUE - Bump github.com/go-jose/go-jose/v4 from 4.0.4 to 4.0.5 (#2734)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 15:30:54 +01:00
Felix Gateru 986bc38a19 SMQ-2689 - Allow user defined ids for domains (#2696)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-02-25 14:46:15 +01:00
Felix Gateru f96876fe04 SMQ-2705 - Add list groups with no parent group (#2708)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-02-25 10:13:42 +01:00
JeffMboya a5bf63c2c6 SMQ-2678 - Rename SMQ_CLIENTS_AUTH_GRPC_ to SMQ_CLIENTS_GRPC_ (#2721)
Signed-off-by: JeffMboya <jangina.mboya@gmail.com>
2025-02-24 14:22:52 +01:00
dependabot[bot] a4e4527b04 NOISSUE - Bump github.com/nats-io/nats.go from 1.39.0 to 1.39.1 (#2727)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 13:57:21 +01:00
dependabot[bot] 506f67f222 NOISSUE - Bump golang.org/x/crypto from 0.33.0 to 0.34.0 (#2729)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 13:56:51 +01:00
dependabot[bot] 5c0a0237d7 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.7.0 to 9.7.1 (#2728)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 12:53:21 +01:00
dependabot[bot] 2a86caeb3d NOISSUE - Bump github.com/prometheus/client_golang from 1.20.5 to 1.21.0 (#2730)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 11:32:10 +01:00
Steve Munene eaaba5beeb SMQ-2682 - Fix incorrectly referenced field name (#2725)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-02-20 22:41:39 +01:00
Steve Munene 72c762f9cb SMQ-2671 - Add request ID and use it to correlate traces, logs, and events (#2709)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-02-19 13:42:06 +01:00
Arvindh 972fa0b25b NOISSUE - Add role name and domain name in list invitations response (#2720)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-02-19 13:26:55 +01:00
dependabot[bot] da6e3e17a6 NOISSUE - Bump github.com/authzed/spicedb from 1.40.0 to 1.40.1 (#2714)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 09:28:24 +01:00
dependabot[bot] db553d328a NOISSUE - Bump github.com/gofrs/uuid/v5 from 5.3.0 to 5.3.1 (#2715)
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:19 +01:00
dependabot[bot] 3fc7868759 NOISSUE - Bump github.com/spf13/cobra from 1.8.1 to 1.9.1 (#2716)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 09:13:41 +01:00
dependabot[bot] 62a3578e0d NOISSUE - Bump golang from 1.23-alpine to 1.24-alpine in /docker in the docker-dependency group (#2711)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 09:09:47 +01:00
dependabot[bot] 42f48b41ba NOISSUE - Bump github.com/hashicorp/vault/api/auth/approle from 0.8.0 to 0.9.0 (#2713)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 09:09:19 +01:00
Felix Gateru 7667eee725 SMQ - 2435 - Merge invitations into domains service (#2676)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-02-13 16:24:39 +01:00
Felix Gateru 597ad23ba1 NOISSUE - Fix domains path in CI tests workflow (#2697)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-02-11 21:07:24 +01:00
dependabot[bot] 838cfd59a6 NOISSUE - Bump golang.org/x/oauth2 from 0.25.0 to 0.26.0 (#2698)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 21:01:48 +01:00
dependabot[bot] 984d67eaa1 NOISSUE - Bump golang.org/x/crypto from 0.32.0 to 0.33.0 (#2699)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 19:46:13 +01:00
dependabot[bot] 6121c18088 NOISSUE - Bump go.etcd.io/bbolt from 1.3.11 to 1.4.0 (#2691)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 10:38:02 +01:00
dependabot[bot] 392940cfa8 NOISSUE - Bump google.golang.org/protobuf from 1.36.4 to 1.36.5 (#2693)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 10:29:58 +01:00
dependabot[bot] 118d85f1e8 NOISSUE - Bump golang.org/x/sync from 0.10.0 to 0.11.0 (#2690)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 10:28:35 +01:00
dependabot[bot] 236b841182 NOISSUE - Bump github.com/nats-io/nats.go from 1.38.0 to 1.39.0 (#2694)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 09:54:00 +01:00
dependabot[bot] da17597121 NOISSUE - Bump github.com/go-chi/chi/v5 from 5.2.0 to 5.2.1 (#2692)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 09:50:04 +01:00
Steve Munene bd44d1e95a SMQ-2505 - Add Domain ID in all service logs (#2687)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-02-07 11:07:02 +01:00
Felix Gateru 67ab52db90 SMQ-2686 - Fix channel journals (#2685)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-02-06 18:10:35 +01:00
b1ackd0t cff6e7f085 NOISSUE - Use NATS as MQTT broker (#2681)
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-02-03 18:17:35 +01:00
Arvindh 7c6bc9cd7e SMQ 2667 - List all the users who can access the entity (#2673)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-02-03 16:37:51 +01:00
Felix Gateru 484de372ec SMQ - 2546 - Add telemetry aggregation for clients telemetry (#2661)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-02-03 11:37:25 +01:00
Felix Gateru 07dbb86203 SMQ-2546 - Add events to adapters (#2659)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-30 12:45:40 +01:00
dependabot[bot] 53cb10bb89 NOISSUE - Bump github.com/authzed/authzed-go from 1.2.2-0.20250107172318-7fd4159ab2b7 to 1.3.0 (#2668)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 12:07:10 +01:00
Felix Gateru e69730d9d6 NOISSUE - Fix failing channel repo tests (#2662)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
Co-authored-by: Dušan Borovčanin <dusan.borovcanin@abstractmachines.fr>
2025-01-27 14:05:05 +01:00
Arvindh ef328369b8 NOISSUE - Fix Clients, Channels roles initialization and Channels connection Authz (#2663)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-01-27 10:46:45 +01:00
dependabot[bot] e5b2fa2ec7 NOISSUE - Bump google.golang.org/protobuf from 1.36.3 to 1.36.4 (#2665)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-26 18:04:23 +01:00
dependabot[bot] 97f8092868 NOISSUE - Bump github.com/authzed/spicedb from 1.39.1 to 1.40.0 (#2664)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-26 17:56:46 +01:00
dependabot[bot] d2dbc4c44c NOISSUE - Bump google.golang.org/grpc from 1.69.4 to 1.70.0 (#2666)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-26 17:51:47 +01:00
Arvindh d77d005659 NOISSUE - Fix Listing of connections and groups for clients and channels (#2660)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-01-23 10:12:13 +01:00
Arvindh 104c5b3da4 NOISSUE - Fix channels connections (#2658)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-01-21 17:06:22 +01:00
Arvindh 53e39a1dc6 NOISSUE - Add domain events consumer, listing of clients and channels with domains (#2656)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-01-21 14:31:29 +01:00
dependabot[bot] 3cb41fa6e7 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp from 1.33.0 to 1.34.0 (#2657)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-21 14:06:55 +01:00
Arvindh 88d583bfb1 SMQ-2605 - Groups replication with groups events consumer & listing of things and channels (#2639)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-01-20 12:36:50 +01:00
dependabot[bot] a8b12e4461 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc from 0.58.0 to 0.59.0 (#2650)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:22:12 +01:00
dependabot[bot] bc6339bf52 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace from 1.33.0 to 1.34.0 (#2652)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:11:29 +01:00
dependabot[bot] 15d8e94678 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp from 0.58.0 to 0.59.0 (#2653)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:08:40 +01:00
dependabot[bot] 250070dc15 NOISSUE - Bump google.golang.org/protobuf from 1.36.2 to 1.36.3 (#2655)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:05:59 +01:00
dependabot[bot] f7ee4f103c NOISSUE - Bump go.opentelemetry.io/otel/trace from 1.33.0 to 1.34.0 (#2654)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:01:12 +01:00
Felix Gateru fbbe5ff767 SMQ-2648 - Add API and Repository implementation for the Client stats (#2647)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-17 17:14:13 +01:00
Steve Munene 5d755990b7 SMQ-1485 - Add mutual TLS support for gRPC connections (#2646)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-01-17 08:20:41 +01:00
Steve Munene fdea1a753e MG-2358 - Add Domain to Events (#2510)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
Co-authored-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-16 13:13:41 +01:00
Steve Munene d02d63d1eb MG-2048 - Authorize groups and channels with PATs (#2501)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-15 12:15:14 +01:00
Felix Gateru 153d230907 NOISSUE - Update CLI (#2645)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-14 13:07:28 +01:00
Felix Gateru 3a11b54394 NOISSUE - Revert removal of notifier interface (#2643)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-13 10:14:33 +01:00
dependabot[bot] 6fd7e3de63 NOISSUE - Bump google.golang.org/grpc from 1.69.2 to 1.69.4 (#2644)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 10:02:14 +01:00
Steve Munene 33407fad16 NOISSUE - Update CLI (#2642)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-01-10 12:49:38 +01:00
Felix Gateru a9169276e5 SMQ-2629 - Remove Readers and Consumers (#2641)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-10 11:26:39 +01:00
Felix Gateru df5d752c4b SMQ-2629 - Remove Boostrap and Provision services (#2640)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-10 09:56:03 +01:00
dependabot[bot] cd73d36bdf NOISSUE - Bump golang.org/x/oauth2 from 0.24.0 to 0.25.0 (#2634)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-09 09:49:44 +01:00
dependabot[bot] 2b2d8b8a5c NOISSUE - Bump github.com/authzed/authzed-go from 1.2.0 to 1.2.1 (#2638)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 18:03:40 +01:00
dependabot[bot] a052559983 NOISSUE - Bump google.golang.org/protobuf from 1.36.1 to 1.36.2 (#2637)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 17:54:32 +01:00
dependabot[bot] 8de72f88f4 NOISSUE - Bump golang.org/x/crypto from 0.31.0 to 0.32.0 (#2635)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-08 13:06:28 +01:00
Drasko DRASKOVIC d89c199f3a NOISSUE - Update MAINTAINERS (#2625) 2024-12-30 23:56:23 +01:00
Drasko DRASKOVIC 378da932b5 NOISSUE - Fix README badge and docs (#2624) 2024-12-30 23:35:20 +01:00
Drasko DRASKOVIC c89cb41c5b Fix README intro (#2623) 2024-12-30 20:09:39 +01:00
Drasko DRASKOVIC ca0f7ca3e8 NOISSUE - Update README (#2622)
Signed-off-by: Drasko Draskovic <drasko.draskovic@gmail.com>
2024-12-30 19:38:45 +01:00
Steve Munene 6abc52d074 MG-2048 - Authorize clients and users with PATs (#2499)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Felix Gateru <felix.gateru@gmail.com>
Co-authored-by: Arvindh <arvindh91@gmail.com>
2024-12-30 17:41:00 +01:00
Arvindh f12aacd1da NOISSUE - Emit roles event during entity creation (#2620)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2024-12-27 19:34:13 +01:00
Dušan Borovčanin c32d40636d NOISSUE - Add token type check (#2621)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2024-12-25 23:44:57 +01:00
Arvindh 6b16535958 NOISSUE - Use role id instead of name (#2612)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2024-12-25 14:25:43 +01:00
dependabot[bot] 58ba597c62 NOISSUE - Bump google.golang.org/protobuf from 1.36.0 to 1.36.1 (#2619)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-24 10:15:01 +01:00
Felix Gateru 8e552d0a96 SMQ-2568 - Check Domain enabled / disabled status during Authn or Authz (#2586)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Arvindh <arvindh91@gmail.com>
2024-12-24 09:57:32 +01:00
Felix Gateru 4f73a52192 SMQ-2570 - Update SDK to align with new architecture (#2585)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2024-12-23 15:09:06 +01:00
dependabot[bot] 7486317363 NOISSUE - Bump github.com/caarlos0/env/v11 from 11.3.0 to 11.3.1 (#2618)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 10:34:45 +01:00
dependabot[bot] 7ac7b1f9c6 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc from 0.57.0 to 0.58.0 (#2617)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 10:30:27 +01:00
dependabot[bot] 10c6140e3c NOISSUE - Bump github.com/nats-io/nats.go from 1.37.0 to 1.38.0 (#2616)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 10:28:13 +01:00
dependabot[bot] c50bf5bebf NOISSUE - Bump github.com/go-chi/chi/v5 from 5.1.0 to 5.2.0 (#2615)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 10:26:10 +01:00
dependabot[bot] 0e2ae5e5e1 NOISSUE - Bump github.com/jackc/pgx/v5 from 5.7.1 to 5.7.2 (#2614)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 10:24:02 +01:00
dependabot[bot] 1474da8b2e NOISSUE - Bump google.golang.org/grpc from 1.68.1 to 1.69.2 (#2613)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 10:22:20 +01:00
Sammy Kerata Oina e95d1bfbcf NOISSUE - Move gRPC to api package (#2593)
Signed-off-by: Sammy Oina <sammyoina@gmail.com>
2024-12-20 13:04:33 +01:00
Dušan Borovčanin f0d014eba2 NOISSUE - Move API to the common package (#2608)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2024-12-19 18:29:53 +01:00
dorcaslitunya 9e6da193c8 NOISSUE - Remove duplicate DomainID paths (#2607) 2024-12-19 12:39:41 +01:00
Steve Munene e8e17f5530 MG-2048 - Implement Personal Access Tokens (PATs) (#2492)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2024-12-18 10:33:07 +01:00
dependabot[bot] 0d126c3be0 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp from 1.32.0 to 1.33.0 (#2597)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 19:25:13 +01:00
dependabot[bot] d46c8d71a0 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp from 0.57.0 to 0.58.0 (#2598)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 19:18:45 +01:00
dependabot[bot] 99b3e67918 NOISSUE - Bump github.com/caarlos0/env/v11 from 11.2.2 to 11.3.0 (#2599)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 19:17:10 +01:00
dependabot[bot] d6aa51bf24 NOISSUE - Bump go.opentelemetry.io/otel/sdk from 1.32.0 to 1.33.0 (#2596)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 19:12:49 +01:00
dependabot[bot] f288c77893 NOISSUE - Bump google.golang.org/protobuf from 1.35.2 to 1.36.0 (#2600)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-17 16:46:32 +01:00
Felix Gateru f7d0513ad5 SMQ-2587 - Fix creating group with parent and group listing with tree parameter (#2594)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2024-12-17 13:17:55 +01:00
Felix Gateru 8c93dae2ba NOISSUE - Add domains, channels and groups tests to CI (#2595)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2024-12-16 18:48:53 +01:00
dependabot[bot] 42802703d4 NOISSUE - Bump github.com/rubenv/sql-migrate from 1.7.0 to 1.7.1 (#2589)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 10:17:59 +01:00
dependabot[bot] e8e8a4bd8a NOISSUE - Bump go.opentelemetry.io/otel from 1.32.0 to 1.33.0 (#2591)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 10:15:26 +01:00
dependabot[bot] e8d77679e4 NOISSUE - Bump github.com/authzed/spicedb from 1.39.0 to 1.39.1 (#2592)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 10:09:16 +01:00
892 changed files with 103436 additions and 81784 deletions
@@ -5,6 +5,10 @@
coverage:
ignore:
- "tools/*"
- "cmd/*"
- "coap/*"
- "**/mocks*"
- "*/mocks/*"
- "*/middleware/*"
- "pkg/sid/mock.go"
- "pkg/tracing/utils.go"
- "pkg/prometheus/*"
+183
View File
@@ -0,0 +1,183 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Property Based Tests
on:
pull_request:
branches:
- main
paths:
- ".github/workflows/api-tests.yaml"
- "api/**"
- "auth/api/http/**"
- "channels/api/http/**"
- "clients/api/http/**"
- "domains/api/http/**"
- "groups/api/http/**"
- "http/api/**"
- "journal/api/**"
- "users/api/**"
env:
TOKENS_URL: http://localhost:9002/users/tokens/issue
CREATE_DOMAINS_URL: http://localhost:9003/domains
USER_IDENTITY: admin@example.com
USER_SECRET: 12345678
DOMAIN_NAME: demo-test
USERS_URL: http://localhost:9002
DOMAIN_URL: http://localhost:9003
CLIENTS_URL: http://localhost:9006
CHANNELS_URL: http://localhost:9005
GROUPS_URL: http://localhost:9004
HTTP_ADAPTER_URL: http://localhost:8008
AUTH_URL: http://localhost:9001
JOURNAL_URL: http://localhost:9021
jobs:
api-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v5
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: 1.25.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 $CREATE_DOMAINS_URL -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" -d "{\"name\":\"$DOMAIN_NAME\",\"route\":\"$DOMAIN_NAME\"}" | jq -r .id)
echo "USER_TOKEN=$USER_TOKEN" >> $GITHUB_ENV
export CLIENT_SECRET=$(supermq-cli provision test | /usr/bin/grep -Eo '"secret": "[^"]+"' | awk 'NR % 2 == 0' | sed 's/"secret": "\(.*\)"/\1/')
echo "CLIENT_SECRET=$CLIENT_SECRET" >> $GITHUB_ENV
- name: Check for changes in specific paths
uses: dorny/paths-filter@v3
id: changes
with:
filters: |
journal:
- ".github/workflows/api-tests.yaml"
- "apidocs/openapi/journal.yaml"
- "journal/api/**"
auth:
- ".github/workflows/api-tests.yaml"
- "apidocs/openapi/auth.yaml"
- "auth/api/http/**"
domains:
- ".github/workflows/api-tests.yaml"
- "apidocs/openapi/domains.yaml"
- "domains/api/http/**"
http:
- ".github/workflows/api-tests.yaml"
- "apidocs/openapi/http.yaml"
- "http/api/**"
clients:
- ".github/workflows/api-tests.yaml"
- "apidocs/openapi/clients.yaml"
- "clients/api/http/**"
channels:
- ".github/workflows/api-tests.yaml"
- "apidocs/openapi/channels.yaml"
- "channels/api/http/**"
groups:
- ".github/workflows/api-tests.yaml"
- "apidocs/openapi/groups.yaml"
- "groups/api/http/**"
users:
- ".github/workflows/api-tests.yaml"
- "apidocs/openapi/users.yaml"
- "users/api/**"
- name: Run Users API tests
if: steps.changes.outputs.users == 'true'
uses: schemathesis/action@v2.1.0
with:
schema: apidocs/openapi/users.yaml
base-url: ${{ env.USERS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --exclude-operation-id=requestPasswordReset --phases=examples,stateful'
- name: Run Groups API tests
if: steps.changes.outputs.groups == 'true'
uses: schemathesis/action@v2.1.0
with:
schema: apidocs/openapi/groups.yaml
base-url: ${{ env.GROUPS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
- name: Run Clients API tests
if: steps.changes.outputs.clients == 'true'
uses: schemathesis/action@v2.1.0
with:
schema: apidocs/openapi/clients.yaml
base-url: ${{ env.CLIENTS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
- name: Run Channels API tests
if: steps.changes.outputs.channels == 'true'
uses: schemathesis/action@v2.1.0
with:
schema: apidocs/openapi/channels.yaml
base-url: ${{ env.CHANNELS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
- name: Run HTTP Adapter API tests
if: steps.changes.outputs.http == 'true'
uses: schemathesis/action@v2.1.0
with:
schema: apidocs/openapi/http.yaml
base-url: ${{ env.HTTP_ADAPTER_URL }}
checks: all
args: '--header "Authorization: Client ${{ env.CLIENT_SECRET }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
- name: Run Auth API tests
if: steps.changes.outputs.auth == 'true'
uses: schemathesis/action@v2.1.0
with:
schema: apidocs/openapi/auth.yaml
base-url: ${{ env.AUTH_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
- name: Run Domains API tests
if: steps.changes.outputs.domains == 'true'
uses: schemathesis/action@v2.1.0
with:
schema: apidocs/openapi/domains.yaml
base-url: ${{ env.DOMAIN_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
- name: Run Journal API tests
if: steps.changes.outputs.journal == 'true'
uses: schemathesis/action@v2.1.0
with:
schema: apidocs/openapi/journal.yaml
base-url: ${{ env.JOURNAL_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
- name: Stop containers
if: always()
run: make run down args="-v" && make run_addons down args="-v"
-294
View File
@@ -1,294 +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/**"
- "channels/api/http/**"
- "clients/api/http/**"
- "consumers/notifiers/api/**"
- "domains/api/http/**"
- "groups/api/http/**"
- "http/api/**"
- "invitations/api/**"
- "journal/api/**"
- "provision/api/**"
- "readers/api/**"
- "users/api/**"
env:
TOKENS_URL: http://localhost:9002/users/tokens/issue
CREATE_DOMAINS_URL: http://localhost:9003/domains
USER_IDENTITY: admin@example.com
USER_SECRET: 12345678
DOMAIN_NAME: demo-test
USERS_URL: http://localhost:9002
DOMAIN_URL: http://localhost:9003
CLIENTS_URL: http://localhost:9006
CHANNELS_URL: http://localhost:9005
GROUPS_URL: http://localhost:9004
HTTP_ADAPTER_URL: http://localhost:8008
INVITATIONS_URL: http://localhost:9020
AUTH_URL: http://localhost:9001
BOOTSTRAP_URL: http://localhost:9013
CERTS_URL: http://localhost:9019
PROVISION_URL: http://localhost:9016
POSTGRES_READER_URL: http://localhost:9009
TIMESCALE_READER_URL: http://localhost:9011
JOURNAL_URL: http://localhost:9021
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 $CREATE_DOMAINS_URL -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" -d "{\"name\":\"$DOMAIN_NAME\",\"alias\":\"$DOMAIN_NAME\"}" | jq -r .id)
echo "USER_TOKEN=$USER_TOKEN" >> $GITHUB_ENV
export CLIENT_SECRET=$(supermq-cli provision test | /usr/bin/grep -Eo '"secret": "[^"]+"' | awk 'NR % 2 == 0' | sed 's/"secret": "\(.*\)"/\1/')
echo "CLIENT_SECRET=$CLIENT_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/**"
domains:
- ".github/workflows/api-tests.yml"
- "api/openapi/domains.yml"
- "domains/api/http/**"
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/**"
clients:
- ".github/workflows/api-tests.yml"
- "api/openapi/clients.yml"
- "clients/api/http/**"
channels:
- ".github/workflows/api-tests.yml"
- "api/openapi/channels.yml"
- "channels/api/http/**"
groups:
- ".github/workflows/api-tests.yml"
- "api/openapi/groups.yml"
- "groups/api/http/**"
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 Groups API tests
if: steps.changes.outputs.groups == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/groups.yml
base-url: ${{ env.GROUPS_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 Clients API tests
if: steps.changes.outputs.clients == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/clients.yml
base-url: ${{ env.CLIENTS_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 Channels API tests
if: steps.changes.outputs.channels == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/channels.yml
base-url: ${{ env.CHANNELS_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: Client ${{ env.CLIENT_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 Domains API tests
if: steps.changes.outputs.domains == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/domains.yml
base-url: ${{ env.DOMAIN_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"
@@ -12,21 +12,29 @@ 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@v5
- name: Fetch tags for the build
run: |
git fetch --prune --unshallow --tags
- name: Install Go
uses: actions/setup-go@v5
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: 1.22.x
go-version: 1.25.x
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,7 +44,6 @@ jobs:
with:
token: ${{ secrets.CODECOV }}
files: ./coverage/*.out
codecov_yml_path: tools/config/codecov.yml
verbose: true
- name: Set up Docker Build
@@ -51,12 +58,20 @@ jobs:
- name: Compile check for rabbitmq
run: |
SMQ_MESSAGE_BROKER_TYPE=rabbitmq make mqtt
SMQ_MESSAGE_BROKER_TYPE=msg_rabbitmq make mqtt
- name: Compile check for redis
run: |
SMQ_ES_TYPE=redis make mqtt
SMQ_ES_TYPE=es_redis make mqtt
- name: Build and push Dockers
- name: Build and push Docker images
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-smq-images
@@ -0,0 +1,141 @@
# 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@v5
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: 1.25.x
cache-dependency-path: "go.sum"
- name: Set GOBIN
run: echo "GOBIN=$HOME/.local/bin" >> $GITHUB_ENV
- name: Add GOBIN to PATH
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Check for changes in go.mod
run: |
go mod tidy
git diff --exit-code
- name: Check for changes in specific paths
uses: dorny/paths-filter@v3
id: changes
with:
base: main
filters: |
proto:
- ".github/workflows/check-generated-files.yaml"
- "auth.proto"
- "auth/*.pb.go"
- "pkg/messaging/message.proto"
- "pkg/messaging/*.pb.go"
mocks:
- ".github/workflows/check-generated-files.yaml"
- "pkg/sdk/sdk.go"
- "users/postgres/clients.go"
- "users/clients.go"
- "pkg/clients/clients.go"
- "pkg/messaging/pubsub.go"
- "clients/postgres/clients.go"
- "clients/clients.go"
- "pkg/authz.go"
- "pkg/authn.go"
- "auth/domains.go"
- "auth/keys.go"
- "auth/service.go"
- "pkg/events/events.go"
- "pkg/groups/groups.go"
- "users/emailer.go"
- "users/hasher.go"
- "journal/journal.go"
- "consumers/notifier.go"
- name: Set up protoc
if: steps.changes.outputs.proto == 'true'
run: |
PROTOC_VERSION=33.0
PROTOC_GEN_VERSION=v1.36.10
PROTOC_GRPC_VERSION=v1.5.1
# 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: |
for f in $(find . -type f -path '*/mocks/*.go' ! -name 'doc.go'); do
mv $f $f.tmp
done
make mocks
check_mock_changes() {
local file_path=$1
local tmp_file_path=$1.tmp
local entity_name=$2
if ! cmp -s "$file_path" "$tmp_file_path"; then
echo "Error: Generated mocks for $entity_name are out of sync!"
echo "Please run 'make mocks' with mockery version $MOCKERY_VERSION and commit the changes."
exit 1
fi
}
for f in $(find . -type f -path '*/mocks/*.go' ! -name 'doc.go'); do
check_mock_changes $f "$f"
done
-243
View File
@@ -1,243 +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/sdk.go"
- "users/postgres/clients.go"
- "users/clients.go"
- "pkg/clients/clients.go"
- "pkg/messaging/pubsub.go"
- "clients/postgres/clients.go"
- "clients/clients.go"
- "pkg/authz.go"
- "pkg/authn.go"
- "auth/domains.go"
- "auth/keys.go"
- "auth/service.go"
- "pkg/events/events.go"
- "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"
- "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"
- name: Set up protoc
if: steps.changes.outputs.proto == 'true'
run: |
PROTOC_VERSION=29.0
PROTOC_GEN_VERSION=v1.35.2
PROTOC_GRPC_VERSION=v1.5.1
# 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 ./invitations/mocks/repository.go ./invitations/mocks/repository.go.tmp
mv ./invitations/mocks/service.go ./invitations/mocks/service.go.tmp
mv ./auth/mocks/token_client.go ./auth/mocks/token_client.go.tmp
mv ./auth/mocks/authz.go ./auth/mocks/authz.go.tmp
mv ./auth/mocks/keys.go ./auth/mocks/keys.go.tmp
mv ./auth/mocks/service.go ./auth/mocks/service.go.tmp
mv ./bootstrap/mocks/configs.go ./bootstrap/mocks/configs.go.tmp
mv ./bootstrap/mocks/config_reader.go ./bootstrap/mocks/config_reader.go.tmp
mv ./bootstrap/mocks/service.go ./bootstrap/mocks/service.go.tmp
mv ./domains/mocks/domains_client.go ./domains/mocks/domains_client.go.tmp
mv ./domains/mocks/repository.go ./domains/mocks/repository.go.tmp
mv ./domains/mocks/service.go ./domains/mocks/service.go.tmp
mv ./channels/mocks/repository.go ./channels/mocks/repository.go.tmp
mv ./channels/mocks/channels_client.go ./channels/mocks/channels_client.go.tmp
mv ./channels/mocks/service.go ./channels/mocks/service.go.tmp
mv ./groups/private/mocks/service.go ./groups/private/mocks/service.go.tmp
mv ./groups/mocks/repository.go ./groups/mocks/repository.go.tmp
mv ./groups/mocks/groups_client.go ./groups/mocks/groups_client.go.tmp
mv ./groups/mocks/service.go ./groups/mocks/service.go.tmp
mv ./users/mocks/hasher.go ./users/mocks/hasher.go.tmp
mv ./users/mocks/emailer.go ./users/mocks/emailer.go.tmp
mv ./users/mocks/repository.go ./users/mocks/repository.go.tmp
mv ./users/mocks/service.go ./users/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 ./consumers/notifiers/mocks/notifier.go ./consumers/notifiers/mocks/notifier.go.tmp
mv ./consumers/notifiers/mocks/repository.go ./consumers/notifiers/mocks/repository.go.tmp
mv ./consumers/notifiers/mocks/service.go ./consumers/notifiers/mocks/service.go.tmp
mv ./certs/mocks/pki.go ./certs/mocks/pki.go.tmp
mv ./certs/mocks/service.go ./certs/mocks/service.go.tmp
mv ./provision/mocks/service.go ./provision/mocks/service.go.tmp
mv ./clients/private/mocks/service.go ./clients/private/mocks/service.go.tmp
mv ./clients/mocks/repository.go ./clients/mocks/repository.go.tmp
mv ./clients/mocks/clients_client.go ./clients/mocks/clients_client.go.tmp
mv ./clients/mocks/cache.go ./clients/mocks/cache.go.tmp
mv ./clients/mocks/service.go ./clients/mocks/service.go.tmp
mv ./mqtt/mocks/events.go ./mqtt/mocks/events.go.tmp
mv ./readers/mocks/messages.go ./readers/mocks/messages.go.tmp
mv ./pkg/sdk/mocks/sdk.go ./pkg/sdk/mocks/sdk.go.tmp
mv ./pkg/messaging/mocks/pubsub.go ./pkg/messaging/mocks/pubsub.go.tmp
mv ./pkg/authn/mocks/authn.go ./pkg/authn/mocks/authn.go.tmp
mv ./pkg/roles/mocks/rolesRepo.go ./pkg/roles/mocks/rolesRepo.go.tmp
mv ./pkg/roles/mocks/provisioner.go ./pkg/roles/mocks/provisioner.go.tmp
mv ./pkg/roles/mocks/rolemanager.go ./pkg/roles/mocks/rolemanager.go.tmp
mv ./pkg/oauth2/mocks/provider.go ./pkg/oauth2/mocks/provider.go.tmp
mv ./pkg/authz/mocks/authz.go ./pkg/authz/mocks/authz.go.tmp
mv ./pkg/events/mocks/subscriber.go ./pkg/events/mocks/subscriber.go.tmp
mv ./pkg/events/mocks/publisher.go ./pkg/events/mocks/publisher.go.tmp
mv ./pkg/policies/mocks/evaluator.go ./pkg/policies/mocks/evaluator.go.tmp
mv ./pkg/policies/mocks/service.go ./pkg/policies/mocks/service.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 ./invitations/mocks/repository.go " ./invitations/mocks/repository.go"
check_mock_changes ./invitations/mocks/service.go " ./invitations/mocks/service.go"
check_mock_changes ./auth/mocks/token_client.go " ./auth/mocks/token_client.go"
check_mock_changes ./auth/mocks/authz.go " ./auth/mocks/authz.go"
check_mock_changes ./auth/mocks/keys.go " ./auth/mocks/keys.go"
check_mock_changes ./auth/mocks/service.go " ./auth/mocks/service.go"
check_mock_changes ./bootstrap/mocks/configs.go " ./bootstrap/mocks/configs.go"
check_mock_changes ./bootstrap/mocks/config_reader.go " ./bootstrap/mocks/config_reader.go"
check_mock_changes ./bootstrap/mocks/service.go " ./bootstrap/mocks/service.go"
check_mock_changes ./domains/mocks/domains_client.go " ./domains/mocks/domains_client.go"
check_mock_changes ./domains/mocks/repository.go " ./domains/mocks/repository.go"
check_mock_changes ./domains/mocks/service.go " ./domains/mocks/service.go"
check_mock_changes ./channels/mocks/repository.go " ./channels/mocks/repository.go"
check_mock_changes ./channels/mocks/channels_client.go " ./channels/mocks/channels_client.go"
check_mock_changes ./channels/mocks/service.go " ./channels/mocks/service.go"
check_mock_changes ./groups/private/mocks/service.go " ./groups/private/mocks/service.go"
check_mock_changes ./groups/mocks/repository.go " ./groups/mocks/repository.go"
check_mock_changes ./groups/mocks/groups_client.go " ./groups/mocks/groups_client.go"
check_mock_changes ./groups/mocks/service.go " ./groups/mocks/service.go"
check_mock_changes ./users/mocks/hasher.go " ./users/mocks/hasher.go"
check_mock_changes ./users/mocks/emailer.go " ./users/mocks/emailer.go"
check_mock_changes ./users/mocks/repository.go " ./users/mocks/repository.go"
check_mock_changes ./users/mocks/service.go " ./users/mocks/service.go"
check_mock_changes ./journal/mocks/repository.go " ./journal/mocks/repository.go"
check_mock_changes ./journal/mocks/service.go " ./journal/mocks/service.go"
check_mock_changes ./consumers/notifiers/mocks/notifier.go " ./consumers/notifiers/mocks/notifier.go"
check_mock_changes ./consumers/notifiers/mocks/repository.go " ./consumers/notifiers/mocks/repository.go"
check_mock_changes ./consumers/notifiers/mocks/service.go " ./consumers/notifiers/mocks/service.go"
check_mock_changes ./certs/mocks/pki.go " ./certs/mocks/pki.go"
check_mock_changes ./certs/mocks/service.go " ./certs/mocks/service.go"
check_mock_changes ./provision/mocks/service.go " ./provision/mocks/service.go"
check_mock_changes ./clients/private/mocks/service.go " ./clients/private/mocks/service.go"
check_mock_changes ./clients/mocks/repository.go " ./clients/mocks/repository.go"
check_mock_changes ./clients/mocks/clients_client.go " ./clients/mocks/clients_client.go"
check_mock_changes ./clients/mocks/cache.go " ./clients/mocks/cache.go"
check_mock_changes ./clients/mocks/service.go " ./clients/mocks/service.go"
check_mock_changes ./mqtt/mocks/events.go " ./mqtt/mocks/events.go"
check_mock_changes ./readers/mocks/messages.go " ./readers/mocks/messages.go"
check_mock_changes ./pkg/sdk/mocks/sdk.go " ./pkg/sdk/mocks/sdk.go"
check_mock_changes ./pkg/messaging/mocks/pubsub.go " ./pkg/messaging/mocks/pubsub.go"
check_mock_changes ./pkg/authn/mocks/authn.go " ./pkg/authn/mocks/authn.go"
check_mock_changes ./pkg/roles/mocks/rolesRepo.go " ./pkg/roles/mocks/rolesRepo.go"
check_mock_changes ./pkg/roles/mocks/provisioner.go " ./pkg/roles/mocks/provisioner.go"
check_mock_changes ./pkg/roles/mocks/rolemanager.go " ./pkg/roles/mocks/rolemanager.go"
check_mock_changes ./pkg/oauth2/mocks/provider.go " ./pkg/oauth2/mocks/provider.go"
check_mock_changes ./pkg/authz/mocks/authz.go " ./pkg/authz/mocks/authz.go"
check_mock_changes ./pkg/events/mocks/subscriber.go " ./pkg/events/mocks/subscriber.go"
check_mock_changes ./pkg/events/mocks/publisher.go " ./pkg/events/mocks/publisher.go"
check_mock_changes ./pkg/policies/mocks/evaluator.go " ./pkg/policies/mocks/evaluator.go"
check_mock_changes ./pkg/policies/mocks/service.go " ./pkg/policies/mocks/service.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@v5
- 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} \
--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
+4 -4
View File
@@ -13,14 +13,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Swagger UI action
id: swagger-ui-action
uses: blokovi/swagger-ui-action@main
with:
dir: "./api/openapi"
pattern: "*.yml"
dir: "./apidocs/openapi"
pattern: "*.yaml"
debug: "true"
- name: Deploy to GitHub Pages
@@ -28,4 +28,4 @@ jobs:
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: swagger-ui
cname: docs.api.magistrala.abstractmachines.fr
cname: docs.api.supermq.absmach.eu
@@ -15,27 +15,38 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.22.x
go-version: 1.25.x
cache-dependency-path: "go.sum"
- name: Fetch Certs
run: |
make fetch_certs
if [[ -n $(git status --porcelain docker/addons/certs) ]]; then
echo "Certs docker file is not up to date. Please update it"
git diff docker/addons/certs
exit 1
else
exit 0
fi
- name: Install protolint
run: |
go install github.com/yoheimuta/protolint/cmd/protolint@latest
- name: Lint Protobuf Files
run: |
protolint .
protolint .
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
- name: Run linters
uses: golangci/golangci-lint-action@v8
with:
version: v1.60.3
args: --config ./tools/config/golangci.yml
version: v2.4.0
args: --config ./tools/config/.golangci.yaml
- name: Build all Binaries
run: |
@@ -43,11 +54,11 @@ jobs:
- name: Compile check for rabbitmq
run: |
SMQ_MESSAGE_BROKER_TYPE=rabbitmq make mqtt
SMQ_MESSAGE_BROKER_TYPE=msg_rabbitmq make mqtt
- name: Compile check for redis
run: |
SMQ_ES_TYPE=redis make mqtt
SMQ_ES_TYPE=es_redis make mqtt
run-tests:
name: Run tests
@@ -56,14 +67,14 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.22.x
go-version: 1.25.x
cache-dependency-path: "go.sum"
- name: Check for changes in specific paths
@@ -73,7 +84,7 @@ jobs:
base: main
filters: |
workflow:
- ".github/workflows/tests.yml"
- ".github/workflows/tests.yaml"
auth:
- "auth/**"
@@ -84,28 +95,37 @@ jobs:
- "pkg/ulid/**"
- "pkg/uuid/**"
bootstrap:
- "bootstrap/**"
- "cmd/bootstrap/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/sdk/**"
- "pkg/events/**"
certs:
- "certs/**"
- "cmd/certs/**"
channels:
- "channels/**"
- "cmd/channels/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/sdk/**"
- "clients/api/grpc/**"
- "groups/api/grpc/**"
- "domains/api/grpc/**"
- "internal/grpc/**"
cli:
- "cli/**"
- "cmd/cli/**"
- "pkg/sdk/**"
clients:
- "clients/**"
- "cmd/clients/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/ulid/**"
- "pkg/uuid/**"
- "pkg/events/**"
- "groups/api/grpc/**"
- "channels/api/grpc/**"
- "domains/api/grpc/**"
- "internal/grpc/**"
coap:
- "coap/**"
- "cmd/coap/**"
@@ -114,26 +134,26 @@ jobs:
- "clients/**"
- "pkg/messaging/**"
consumers:
- "consumers/**"
- "cmd/postgres-writer/**"
- "cmd/timescale-writer/**"
- "cmd/smpp-notifier/**"
- "cmd/smtp-notifier/**"
domains:
- "domains/**"
- "cmd/domains/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "internal/grpc/**"
groups:
- "groups/**"
- "cmd/groups/**"
- "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/**"
- "clients/api/grpc/**"
- "channels/api/grpc/**"
- "domains/api/grpc/**"
- "internal/grpc/**"
http:
- "http/**"
@@ -147,13 +167,13 @@ jobs:
internal:
- "internal/**"
invitations:
- "invitations/**"
- "cmd/invitations/**"
journal:
- "journal/**"
- "cmd/journal/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/sdk/**"
- "pkg/events/**"
logger:
- "logger/**"
@@ -186,19 +206,15 @@ jobs:
- "pkg/errors/**"
- "pkg/groups/**"
- "auth/**"
- "bootstrap/**"
- "certs/**"
- "consumers/**"
- "http/**"
- "internal/*"
- "internal/api/**"
- "internal/apiutil/**"
- "internal/groups/**"
- "invitations/**"
- "provision/**"
- "readers/**"
- "clients/**"
- "users/**"
- "channels/**"
- "domains/**"
- "groups/**"
- "journal/**"
- "api/http/**"
pkg-transformers:
- "pkg/transformers/**"
@@ -209,31 +225,6 @@ jobs:
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"
- "clients/**"
- "auth/**"
clients:
- "clients/**"
- "cmd/clients/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/ulid/**"
- "pkg/uuid/**"
- "pkg/events/**"
users:
- "users/**"
- "cmd/users/**"
@@ -256,7 +247,7 @@ jobs:
run: |
mkdir coverage
- name: Run Journal tests
- 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/...
@@ -266,15 +257,10 @@ jobs:
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'
- name: Run domains tests
if: steps.changes.outputs.domains == '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/...
go test --race -v -count=1 -coverprofile=coverage/domains.out ./domains/...
- name: Run cli tests
if: steps.changes.outputs.cli == 'true' || steps.changes.outputs.workflow == 'true'
@@ -286,11 +272,6 @@ jobs:
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: |
@@ -301,11 +282,6 @@ jobs:
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: |
@@ -356,26 +332,26 @@ jobs:
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-uuid.out ./pkg/uuid/...
- name: Run provision tests
if: steps.changes.outputs.provision == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/provision.out ./provision/...
- name: Run readers tests
if: steps.changes.outputs.readers == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/readers.out ./readers/...
- name: Run clients tests
if: steps.changes.outputs.clients == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/clients.out ./clients/...
- name: Run channels tests
if: steps.changes.outputs.channels == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/channels.out ./channels/...
- 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 groups tests
if: steps.changes.outputs.groups == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/groups.out ./groups/...
- name: Run WebSocket tests
if: steps.changes.outputs.ws == 'true' || steps.changes.outputs.workflow == 'true'
run: |
@@ -386,5 +362,4 @@ jobs:
with:
token: ${{ secrets.CODECOV }}
files: ./coverage/*.out
codecov_yml_path: tools/config/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/
# Ignore Openbao data directory as it contains runtime-generated data
docker/addons/certs/openbao/
+1 -1
View File
@@ -7,7 +7,7 @@
[[drasko]]
Name = "Drasko Draskovic"
Email = "draasko.draskovic@abstractmachines.fr"
Email = "drasko@abstractmachines.fr"
GitHub = "drasko"
# However, this role serves only in dead-lock events, or in a special and very rare cases
+56 -50
View File
@@ -3,9 +3,8 @@
SMQ_DOCKER_IMAGE_NAME_PREFIX ?= supermq
BUILD_DIR ?= build
SERVICES = auth users clients groups channels domains http coap ws postgres-writer postgres-reader timescale-writer \
timescale-reader cli bootstrap mqtt provision certs invitations journal
TEST_API_SERVICES = journal auth bootstrap certs http invitations notifiers provision readers clients users channels groups domains
SERVICES = auth users clients groups channels domains http coap ws cli mqtt journal
TEST_API_SERVICES = journal auth certs http clients users channels groups domains
TEST_API = $(addprefix test_api_,$(TEST_API_SERVICES))
DOCKERS = $(addprefix docker_,$(SERVICES))
DOCKERS_DEV = $(addprefix docker_dev_,$(SERVICES))
@@ -14,34 +13,35 @@ GOARCH ?= amd64
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 restart
DEFAULT_DOCKER_COMPOSE_COMMAND := up
GRPC_MTLS_CERT_FILES_EXISTS = 0
MOCKERY_VERSION=v2.43.2
INTERNAL_PROTO_GEN_OUT_DIR=internal/grpc
MOCKERY = $(GOBIN)/mockery
MOCKERY_VERSION=3.5.5
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 ($(SMQ_MESSAGE_BROKER_TYPE),)
SMQ_MESSAGE_BROKER_TYPE := $(SMQ_MESSAGE_BROKER_TYPE)
SMQ_MESSAGE_BROKER_TYPE := $(SMQ_MESSAGE_BROKER_TYPE)
else
SMQ_MESSAGE_BROKER_TYPE=nats
SMQ_MESSAGE_BROKER_TYPE=msg_nats
endif
ifneq ($(SMQ_ES_TYPE),)
SMQ_ES_TYPE := $(SMQ_ES_TYPE)
SMQ_ES_TYPE := $(SMQ_ES_TYPE)
else
SMQ_ES_TYPE=nats
SMQ_ES_TYPE=es_nats
endif
define compile_service
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) \
go build -tags $(SMQ_MESSAGE_BROKER_TYPE) --tags $(SMQ_ES_TYPE) -ldflags "-s -w \
go build -tags $(SMQ_MESSAGE_BROKER_TYPE) -tags $(SMQ_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)'" \
@@ -73,9 +73,9 @@ define make_docker_dev
-f docker/Dockerfile.dev ./build
endef
ADDON_SERVICES = bootstrap journal provision certs timescale-reader timescale-writer postgres-reader postgres-writer
ADDON_SERVICES = journal certs
EXTERNAL_SERVICES = vault prometheus
EXTERNAL_SERVICES = prometheus
ifneq ($(filter run%,$(firstword $(MAKECMDGOALS))),)
temp_args := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
@@ -106,7 +106,7 @@ clean:
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
@@ -118,23 +118,28 @@ install:
cp $$file $(GOBIN)/supermq-`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
mocks: $(MOCKERY)
@$(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
DIRS = consumers readers postgres internal
test: mocks
mkdir -p coverage
@for dir in $(DIRS); do \
go test -v --race -count 1 -tags test -coverprofile=coverage/$$dir.out $$(go list ./... | grep $$dir | grep -v 'cmd'); \
done
go test -v --race -count 1 -tags test -coverprofile=coverage/coverage.out $$(go list ./... | grep -v 'consumers\|readers\|postgres\|internal\|cmd\|middleware')
go test -v --race -failfast -count 1 -tags test -coverprofile=coverage/$$dir.out $$(go list ./... | grep $$dir | grep -v 'cmd'); \
done
go test -v --race -failfast -count 1 -tags test -coverprofile=coverage/coverage.out $$(go list ./... | grep -v 'consumers\|readers\|postgres\|internal\|cmd\|middleware')
define test_api_service
$(eval svc=$(subst test_api_,,$(1)))
@which st > /dev/null || (echo "schemathesis not found, please install it from https://github.com/schemathesis/schemathesis#getting-started" && exit 1)
@which uv > /dev/null || (echo "uv not found, please install it from https://github.com/astral-sh/uv" && exit 1)
@if [ -z "$(USER_TOKEN)" ]; then \
echo "USER_TOKEN is not set"; \
@@ -149,21 +154,22 @@ define test_api_service
fi
@if [ "$(svc)" = "http" ]; then \
st run api/openapi/$(svc).yml \
uvx schemathesis run apidocs/openapi/$(svc).yaml \
--checks all \
--base-url $(2) \
--url $(2) \
--header "Authorization: Client $(CLIENT_SECRET)" \
--contrib-openapi-formats-uuid \
--hypothesis-suppress-health-check=filter_too_much \
--stateful=links; \
--suppress-health-check=filter_too_much \
--exclude-checks=positive_data_acceptance \
--phases=examples,stateful; \
else \
st run api/openapi/$(svc).yml \
uvx schemathesis run apidocs/openapi/$(svc).yaml \
--checks all \
--base-url $(2) \
--url $(2) \
--header "Authorization: Bearer $(USER_TOKEN)" \
--contrib-openapi-formats-uuid \
--hypothesis-suppress-health-check=filter_too_much \
--stateful=links; \
--suppress-health-check=filter_too_much \
--exclude-checks=positive_data_acceptance \
--exclude-operation-id=requestPasswordReset \
--phases=examples,stateful; \
fi
endef
@@ -173,12 +179,8 @@ test_api_domains: TEST_API_URL := http://localhost:9003
test_api_channels: TEST_API_URL := http://localhost:9005
test_api_groups: TEST_API_URL := http://localhost:9004
test_api_http: TEST_API_URL := http://localhost:8008
test_api_invitations: TEST_API_URL := http://localhost:9020
test_api_auth: TEST_API_URL := http://localhost:9001
test_api_bootstrap: TEST_API_URL := http://localhost:9013
test_api_certs: TEST_API_URL := http://localhost:9019
test_api_provision: TEST_API_URL := http://localhost:9016
test_api_readers: TEST_API_URL := http://localhost:9009 # This can be the URL of any reader service.
test_api_journal: TEST_API_URL := http://localhost:9021
$(TEST_API):
@@ -186,8 +188,8 @@ $(TEST_API):
proto:
protoc -I. --go_out=. --go_opt=paths=source_relative pkg/messaging/*.proto
mkdir -p $(INTERNAL_PROTO_GEN_OUT_DIR)
protoc -I $(INTERNAL_PROTO_DIR) --go_out=$(INTERNAL_PROTO_GEN_OUT_DIR) --go_opt=paths=source_relative --go-grpc_out=$(INTERNAL_PROTO_GEN_OUT_DIR) --go-grpc_opt=paths=source_relative $(INTERNAL_PROTO_FILES)
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,$(@))
@@ -230,22 +232,18 @@ grpc_mtls_certs:
check_tls:
ifeq ($(GRPC_TLS),true)
@unset GRPC_MTLS
@echo "gRPC TLS is enabled"
GRPC_MTLS=
$(eval GRPC_MTLS :=)
else
@unset GRPC_TLS
GRPC_TLS=
$(eval GRPC_TLS :=)
endif
check_mtls:
ifeq ($(GRPC_MTLS),true)
@unset GRPC_TLS
@echo "gRPC MTLS is enabled"
GRPC_TLS=
$(eval GRPC_TLS :=)
else
@unset GRPC_MTLS
GRPC_MTLS=
$(eval GRPC_MTLS :=)
endif
check_certs: check_mtls check_tls
@@ -257,14 +255,22 @@ endif
endif
endif
fetch_certs:
@./scripts/certs.sh
run: check_certs
docker compose -f docker/docker-compose.yml --env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
docker compose -f docker/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))))
@docker compose -f docker/docker-compose.yaml --env-file ./docker/.env -p $(DOCKER_PROJECT) up -d auth domains jaeger
@for SVC in $(RUN_ADDON_ARGS); do \
SMQ_ADDONS_CERTS_PATH_PREFIX="../." docker compose -f docker/addons/$$SVC/docker-compose.yml -p $(DOCKER_PROJECT) --env-file ./docker/.env $(DOCKER_COMPOSE_COMMAND) $(args) & \
if [ "$$SVC" = "certs" ]; then \
docker compose -f docker/addons/$$SVC/docker-compose.yaml -f docker/certs-docker-compose-override.yaml --env-file ./docker/.env --env-file ./docker/addons/$$SVC/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args) & \
else \
SMQ_ADDONS_CERTS_PATH_PREFIX="../." docker compose -f docker/addons/$$SVC/docker-compose.yaml -p $(DOCKER_PROJECT) --env-file ./docker/.env $(DOCKER_COMPOSE_COMMAND) $(args) & \
fi; \
done
run_live: check_certs
GOPATH=$(go env GOPATH) docker compose -f docker/docker-compose.yml -f docker/docker-compose-live.yaml --env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
GOPATH=$(go env GOPATH) docker compose -f docker/docker-compose.yaml -f docker/docker-compose-live.yaml --env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
+66 -141
View File
@@ -1,117 +1,96 @@
# SuperMQ
<div align="center">
[![Check License Header](https://github.com/absmach/supermq/actions/workflows/check-license.yaml/badge.svg?branch=main)](https://github.com/absmach/supermq/actions/workflows/check-license.yaml)
[![Check the consistency of generated files](https://github.com/absmach/supermq/actions/workflows/check-generated-files.yml/badge.svg?branch=main)](https://github.com/absmach/supermq/actions/workflows/check-generated-files.yml)
[![Continuous Delivery](https://github.com/absmach/supermq/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/absmach/supermq/actions/workflows/build.yml)
[![go report card][grc-badge]][grc-url]
[![coverage][cov-badge]][cov-url]
[![license][license]](LICENSE)
[![chat][gitter-badge]][gitter]
# SuperMQ
**Planetary event-driven infrastructure**
**Made with ❤️ by [Abstract Machines](https://abstractmachines.fr/)**
[![Build Status](https://github.com/absmach/supermq/actions/workflows/build.yaml/badge.svg?branch=main)](https://github.com/absmach/supermq/actions/workflows/build.yaml)
[![Check License Header](https://github.com/absmach/supermq/actions/workflows/check-license.yaml/badge.svg?branch=main)](https://github.com/absmach/supermq/actions/workflows/check-license.yaml)
[![Check Generated Files](https://github.com/absmach/supermq/actions/workflows/check-generated-files.yaml/badge.svg?branch=main)](https://github.com/absmach/supermq/actions/workflows/check-generated-files.yaml)
[![Go Report Card](https://goreportcard.com/badge/github.com/absmach/supermq)](https://goreportcard.com/report/github.com/absmach/supermq)
[![Coverage](https://codecov.io/gh/absmach/supermq/graph/badge.svg?token=nPCEr5nW8S)](https://codecov.io/gh/absmach/supermq)
[![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://docs.supermq.abstractmachines.fr) | [Contributing](CONTRIBUTING.md) | [Website](https://abstractmachines.fr/) | [Chat](https://matrix.to/#/#supermq:matrix.org)
![banner][banner]
</div>
SuperMQ is modern, scalable, secure, open-source, and patent-free cloud platform for messaging and event-driven architecture (EDA) written in Go.
It accepts user and client (device, user, application) connections over various network protocols (i.e. HTTP, MQTT, WebSocket, CoAP), thus making a seamless bridge between them. It is used as the architecture backbone for building complex distributed solutions.
For more details, check out the [official documentation][docs].
For extra bits and services see [our contrib repository][contrib].
## Introduction 📖
## Features
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.
- 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
## Why SuperMQ Stands Out 🚀
## Prerequisites
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, SuperMQ has you covered. 🌐✨
The following are needed to run SuperMQ:
## Key Features 🌟
- [Docker](https://docs.docker.com/install/) (version 26.0.0)
- **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. 🐳☸️
Developing SuperMQ will also require:
## Installation 🛠️
- [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:
Clone the repository and start SuperMQ services:
```bash
docker compose -f docker/docker-compose.yml --env-file docker/.env -p git_github_com_absmach_supermq_git_ up
git clone https://github.com/absmach/supermq.git
cd supermq
docker compose -f docker/docker-compose.yaml --env-file docker/.env up
```
This will bring up the SuperMQ docker services and interconnect them. This command can also be executed using the project's included Makefile:
Or use the [Makefile](Makefile) for a simpler command:
```bash
make run
```
If you want to run services from specific release checkout code from github and make sure that
`SMQ_RELEASE_TAG` in [.env](.env) is being set to match the release version
For production deployments, check our [Kubernetes guide](https://docs.supermq.abstractmachines.fr/kubernetes). ⚙️
```bash
git checkout tags/<release_number> -b <release_number>
# e.g. `git checkout tags/0.13.0 -b 0.13.0`
```
### Usage 📤📥
Check that `.env` file contains:
```bash
SMQ_RELEASE_TAG=<release_number>
```
> `docker-compose` should be used for development and testing deployments. For production we suggest using [Kubernetes](https://docs.supermq.abstractmachines.fr/kubernetes).
## Usage
The quickest way to start using SuperMQ is via the CLI. The latest version can be downloaded from the [official releases page][releases].
It can also be built and used from the project's root directory:
#### 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.supermq.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 [SuperMQ official docs page][docs]. Documentation is auto-generated, checkout the instructions on [official docs repository](https://github.com/absmach/supermq-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://docs.supermq.abstractmachines.fr/cli) for more details.
Main architect and BDFL of SuperMQ 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://docs.supermq.abstractmachines.fr).
Besides them, SuperMQ 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/supermq-docs).
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.
The SuperMQ 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 SuperMQ 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
## Community and Contributing 🤝
Thank you for your interest in SuperMQ and the desire to contribute!
@@ -119,75 +98,21 @@ Thank you for your interest in SuperMQ and the desire to contribute!
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 SuperMQ 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://abstractmachines.fr/)** 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][FOSSA]][FOSSA]
Ready to build the future of messaging and event-driven systems? Let's get started! 🚀
## Data Collection for SuperMQ
SuperMQ 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 SuperMQ 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 SuperMQ.
- **SuperMQ 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:
`SMQ_SEND_TELEMETRY=false`
By utilizing SuperMQ, you actively contribute to its improvement. Together, we can build a more robust and efficient platform. Thank you for your trust in SuperMQ!
[banner]: https://github.com/absmach/supermq-docs/blob/main/docs/img/gopherBanner.jpg
[docs]: https://docs.supermq.abstractmachines.fr
[docker]: https://www.docker.com
[forum]: https://groups.google.com/forum/#!forum/mainflux
[gitter]: https://gitter.im/absmach/supermq?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/supermq
[grc-url]: https://goreportcard.com/report/github.com/absmach/supermq
[cov-badge]: https://codecov.io/gh/absmach/supermq/graph/badge.svg?token=nPCEr5nW8S
[cov-url]: https://codecov.io/gh/absmach/supermq
[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/supermq/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
[FOSSA]: https://app.fossa.com/api/projects/git%2Bgithub.com%2Fabsmach%2Fsupermq.svg?type=small
+1 -1
View File
@@ -2,5 +2,5 @@
// SPDX-License-Identifier: Apache-2.0
// Package api contains commonly used constants and functions
// for the HTTP endpoints.
// for the HTTP and gRPC API.
package api
+485
View File
@@ -0,0 +1,485 @@
// 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: auth/v1/auth.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type AuthNReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthNReq) Reset() {
*x = AuthNReq{}
mi := &file_auth_v1_auth_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthNReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthNReq) ProtoMessage() {}
func (x *AuthNReq) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthNReq.ProtoReflect.Descriptor instead.
func (*AuthNReq) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{0}
}
func (x *AuthNReq) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
type AuthNRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // token id
UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // user id
UserRole uint32 `protobuf:"varint,3,opt,name=user_role,json=userRole,proto3" json:"user_role,omitempty"` // user role
Verified bool `protobuf:"varint,4,opt,name=verified,proto3" json:"verified,omitempty"` // verified user
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthNRes) Reset() {
*x = AuthNRes{}
mi := &file_auth_v1_auth_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthNRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthNRes) ProtoMessage() {}
func (x *AuthNRes) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthNRes.ProtoReflect.Descriptor instead.
func (*AuthNRes) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{1}
}
func (x *AuthNRes) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *AuthNRes) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *AuthNRes) GetUserRole() uint32 {
if x != nil {
return x.UserRole
}
return 0
}
func (x *AuthNRes) GetVerified() bool {
if x != nil {
return x.Verified
}
return false
}
type AuthZReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
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"` // Client 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"` // Client, User, Group
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthZReq) Reset() {
*x = AuthZReq{}
mi := &file_auth_v1_auth_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthZReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthZReq) ProtoMessage() {}
func (x *AuthZReq) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[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 AuthZReq.ProtoReflect.Descriptor instead.
func (*AuthZReq) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{2}
}
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 AuthZPatReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // User id
PatId string `protobuf:"bytes,2,opt,name=pat_id,json=patId,proto3" json:"pat_id,omitempty"` // Pat id
EntityType uint32 `protobuf:"varint,3,opt,name=entity_type,json=entityType,proto3" json:"entity_type,omitempty"` // Entity type
OptionalDomainId string `protobuf:"bytes,4,opt,name=optional_domain_id,json=optionalDomainId,proto3" json:"optional_domain_id,omitempty"` // Optional domain id
Operation uint32 `protobuf:"varint,6,opt,name=operation,proto3" json:"operation,omitempty"` // Operation
EntityId string `protobuf:"bytes,7,opt,name=entity_id,json=entityId,proto3" json:"entity_id,omitempty"` // EntityID
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthZPatReq) Reset() {
*x = AuthZPatReq{}
mi := &file_auth_v1_auth_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthZPatReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthZPatReq) ProtoMessage() {}
func (x *AuthZPatReq) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthZPatReq.ProtoReflect.Descriptor instead.
func (*AuthZPatReq) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{3}
}
func (x *AuthZPatReq) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *AuthZPatReq) GetPatId() string {
if x != nil {
return x.PatId
}
return ""
}
func (x *AuthZPatReq) GetEntityType() uint32 {
if x != nil {
return x.EntityType
}
return 0
}
func (x *AuthZPatReq) GetOptionalDomainId() string {
if x != nil {
return x.OptionalDomainId
}
return ""
}
func (x *AuthZPatReq) GetOperation() uint32 {
if x != nil {
return x.Operation
}
return 0
}
func (x *AuthZPatReq) GetEntityId() string {
if x != nil {
return x.EntityId
}
return ""
}
type AuthZRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthZRes) Reset() {
*x = AuthZRes{}
mi := &file_auth_v1_auth_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthZRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthZRes) ProtoMessage() {}
func (x *AuthZRes) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[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 AuthZRes.ProtoReflect.Descriptor instead.
func (*AuthZRes) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{4}
}
func (x *AuthZRes) GetAuthorized() bool {
if x != nil {
return x.Authorized
}
return false
}
func (x *AuthZRes) GetId() string {
if x != nil {
return x.Id
}
return ""
}
var File_auth_v1_auth_proto protoreflect.FileDescriptor
const file_auth_v1_auth_proto_rawDesc = "" +
"\n" +
"\x12auth/v1/auth.proto\x12\aauth.v1\" \n" +
"\bAuthNReq\x12\x14\n" +
"\x05token\x18\x01 \x01(\tR\x05token\"l\n" +
"\bAuthNRes\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x17\n" +
"\auser_id\x18\x02 \x01(\tR\x06userId\x12\x1b\n" +
"\tuser_role\x18\x03 \x01(\rR\buserRole\x12\x1a\n" +
"\bverified\x18\x04 \x01(\bR\bverified\"\xa2\x02\n" +
"\bAuthZReq\x12\x16\n" +
"\x06domain\x18\x01 \x01(\tR\x06domain\x12!\n" +
"\fsubject_type\x18\x02 \x01(\tR\vsubjectType\x12!\n" +
"\fsubject_kind\x18\x03 \x01(\tR\vsubjectKind\x12)\n" +
"\x10subject_relation\x18\x04 \x01(\tR\x0fsubjectRelation\x12\x18\n" +
"\asubject\x18\x05 \x01(\tR\asubject\x12\x1a\n" +
"\brelation\x18\x06 \x01(\tR\brelation\x12\x1e\n" +
"\n" +
"permission\x18\a \x01(\tR\n" +
"permission\x12\x16\n" +
"\x06object\x18\b \x01(\tR\x06object\x12\x1f\n" +
"\vobject_type\x18\t \x01(\tR\n" +
"objectType\"\xc7\x01\n" +
"\vAuthZPatReq\x12\x17\n" +
"\auser_id\x18\x01 \x01(\tR\x06userId\x12\x15\n" +
"\x06pat_id\x18\x02 \x01(\tR\x05patId\x12\x1f\n" +
"\ventity_type\x18\x03 \x01(\rR\n" +
"entityType\x12,\n" +
"\x12optional_domain_id\x18\x04 \x01(\tR\x10optionalDomainId\x12\x1c\n" +
"\toperation\x18\x06 \x01(\rR\toperation\x12\x1b\n" +
"\tentity_id\x18\a \x01(\tR\bentityId\":\n" +
"\bAuthZRes\x12\x1e\n" +
"\n" +
"authorized\x18\x01 \x01(\bR\n" +
"authorized\x12\x0e\n" +
"\x02id\x18\x02 \x01(\tR\x02id2\xf0\x01\n" +
"\vAuthService\x123\n" +
"\tAuthorize\x12\x11.auth.v1.AuthZReq\x1a\x11.auth.v1.AuthZRes\"\x00\x129\n" +
"\fAuthorizePAT\x12\x14.auth.v1.AuthZPatReq\x1a\x11.auth.v1.AuthZRes\"\x00\x126\n" +
"\fAuthenticate\x12\x11.auth.v1.AuthNReq\x1a\x11.auth.v1.AuthNRes\"\x00\x129\n" +
"\x0fAuthenticatePAT\x12\x11.auth.v1.AuthNReq\x1a\x11.auth.v1.AuthNRes\"\x00B-Z+github.com/absmach/supermq/api/grpc/auth/v1b\x06proto3"
var (
file_auth_v1_auth_proto_rawDescOnce sync.Once
file_auth_v1_auth_proto_rawDescData []byte
)
func file_auth_v1_auth_proto_rawDescGZIP() []byte {
file_auth_v1_auth_proto_rawDescOnce.Do(func() {
file_auth_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_auth_v1_auth_proto_rawDesc), len(file_auth_v1_auth_proto_rawDesc)))
})
return file_auth_v1_auth_proto_rawDescData
}
var file_auth_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_auth_v1_auth_proto_goTypes = []any{
(*AuthNReq)(nil), // 0: auth.v1.AuthNReq
(*AuthNRes)(nil), // 1: auth.v1.AuthNRes
(*AuthZReq)(nil), // 2: auth.v1.AuthZReq
(*AuthZPatReq)(nil), // 3: auth.v1.AuthZPatReq
(*AuthZRes)(nil), // 4: auth.v1.AuthZRes
}
var file_auth_v1_auth_proto_depIdxs = []int32{
2, // 0: auth.v1.AuthService.Authorize:input_type -> auth.v1.AuthZReq
3, // 1: auth.v1.AuthService.AuthorizePAT:input_type -> auth.v1.AuthZPatReq
0, // 2: auth.v1.AuthService.Authenticate:input_type -> auth.v1.AuthNReq
0, // 3: auth.v1.AuthService.AuthenticatePAT:input_type -> auth.v1.AuthNReq
4, // 4: auth.v1.AuthService.Authorize:output_type -> auth.v1.AuthZRes
4, // 5: auth.v1.AuthService.AuthorizePAT:output_type -> auth.v1.AuthZRes
1, // 6: auth.v1.AuthService.Authenticate:output_type -> auth.v1.AuthNRes
1, // 7: auth.v1.AuthService.AuthenticatePAT:output_type -> auth.v1.AuthNRes
4, // [4:8] is the sub-list for method output_type
0, // [0:4] 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_v1_auth_proto_init() }
func file_auth_v1_auth_proto_init() {
if File_auth_v1_auth_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_auth_v1_auth_proto_rawDesc), len(file_auth_v1_auth_proto_rawDesc)),
NumEnums: 0,
NumMessages: 5,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_auth_v1_auth_proto_goTypes,
DependencyIndexes: file_auth_v1_auth_proto_depIdxs,
MessageInfos: file_auth_v1_auth_proto_msgTypes,
}.Build()
File_auth_v1_auth_proto = out.File
file_auth_v1_auth_proto_goTypes = nil
file_auth_v1_auth_proto_depIdxs = nil
}
@@ -4,7 +4,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.29.0
// - protoc v6.33.0
// source: auth/v1/auth.proto
package v1
@@ -22,8 +22,10 @@ import (
const _ = grpc.SupportPackageIsVersion9
const (
AuthService_Authorize_FullMethodName = "/auth.v1.AuthService/Authorize"
AuthService_Authenticate_FullMethodName = "/auth.v1.AuthService/Authenticate"
AuthService_Authorize_FullMethodName = "/auth.v1.AuthService/Authorize"
AuthService_AuthorizePAT_FullMethodName = "/auth.v1.AuthService/AuthorizePAT"
AuthService_Authenticate_FullMethodName = "/auth.v1.AuthService/Authenticate"
AuthService_AuthenticatePAT_FullMethodName = "/auth.v1.AuthService/AuthenticatePAT"
)
// AuthServiceClient is the client API for AuthService service.
@@ -34,7 +36,9 @@ const (
// and authorization functionalities for SuperMQ services.
type AuthServiceClient interface {
Authorize(ctx context.Context, in *AuthZReq, opts ...grpc.CallOption) (*AuthZRes, error)
AuthorizePAT(ctx context.Context, in *AuthZPatReq, opts ...grpc.CallOption) (*AuthZRes, error)
Authenticate(ctx context.Context, in *AuthNReq, opts ...grpc.CallOption) (*AuthNRes, error)
AuthenticatePAT(ctx context.Context, in *AuthNReq, opts ...grpc.CallOption) (*AuthNRes, error)
}
type authServiceClient struct {
@@ -55,6 +59,16 @@ func (c *authServiceClient) Authorize(ctx context.Context, in *AuthZReq, opts ..
return out, nil
}
func (c *authServiceClient) AuthorizePAT(ctx context.Context, in *AuthZPatReq, opts ...grpc.CallOption) (*AuthZRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AuthZRes)
err := c.cc.Invoke(ctx, AuthService_AuthorizePAT_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) Authenticate(ctx context.Context, in *AuthNReq, opts ...grpc.CallOption) (*AuthNRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AuthNRes)
@@ -65,6 +79,16 @@ func (c *authServiceClient) Authenticate(ctx context.Context, in *AuthNReq, opts
return out, nil
}
func (c *authServiceClient) AuthenticatePAT(ctx context.Context, in *AuthNReq, opts ...grpc.CallOption) (*AuthNRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AuthNRes)
err := c.cc.Invoke(ctx, AuthService_AuthenticatePAT_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthServiceServer is the server API for AuthService service.
// All implementations must embed UnimplementedAuthServiceServer
// for forward compatibility.
@@ -73,7 +97,9 @@ func (c *authServiceClient) Authenticate(ctx context.Context, in *AuthNReq, opts
// and authorization functionalities for SuperMQ services.
type AuthServiceServer interface {
Authorize(context.Context, *AuthZReq) (*AuthZRes, error)
AuthorizePAT(context.Context, *AuthZPatReq) (*AuthZRes, error)
Authenticate(context.Context, *AuthNReq) (*AuthNRes, error)
AuthenticatePAT(context.Context, *AuthNReq) (*AuthNRes, error)
mustEmbedUnimplementedAuthServiceServer()
}
@@ -87,9 +113,15 @@ type UnimplementedAuthServiceServer struct{}
func (UnimplementedAuthServiceServer) Authorize(context.Context, *AuthZReq) (*AuthZRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method Authorize not implemented")
}
func (UnimplementedAuthServiceServer) AuthorizePAT(context.Context, *AuthZPatReq) (*AuthZRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method AuthorizePAT not implemented")
}
func (UnimplementedAuthServiceServer) Authenticate(context.Context, *AuthNReq) (*AuthNRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method Authenticate not implemented")
}
func (UnimplementedAuthServiceServer) AuthenticatePAT(context.Context, *AuthNReq) (*AuthNRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method AuthenticatePAT not implemented")
}
func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {}
func (UnimplementedAuthServiceServer) testEmbeddedByValue() {}
@@ -129,6 +161,24 @@ func _AuthService_Authorize_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler)
}
func _AuthService_AuthorizePAT_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthZPatReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).AuthorizePAT(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_AuthorizePAT_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).AuthorizePAT(ctx, req.(*AuthZPatReq))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_Authenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthNReq)
if err := dec(in); err != nil {
@@ -147,6 +197,24 @@ func _AuthService_Authenticate_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _AuthService_AuthenticatePAT_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthNReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).AuthenticatePAT(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_AuthenticatePAT_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).AuthenticatePAT(ctx, req.(*AuthNReq))
}
return interceptor(ctx, in, info, handler)
}
// AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -158,10 +226,18 @@ var AuthService_ServiceDesc = grpc.ServiceDesc{
MethodName: "Authorize",
Handler: _AuthService_Authorize_Handler,
},
{
MethodName: "AuthorizePAT",
Handler: _AuthService_AuthorizePAT_Handler,
},
{
MethodName: "Authenticate",
Handler: _AuthService_Authenticate_Handler,
},
{
MethodName: "AuthenticatePAT",
Handler: _AuthService_AuthenticatePAT_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "auth/v1/auth.proto",
@@ -3,18 +3,19 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.2
// protoc v5.29.0
// protoc-gen-go v1.36.10
// protoc v6.33.0
// source: channels/v1/channels.proto
package v1
import (
v1 "github.com/absmach/supermq/internal/grpc/common/v1"
v1 "github.com/absmach/supermq/api/grpc/common/v1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -25,11 +26,10 @@ const (
)
type RemoveClientConnectionsReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
unknownFields protoimpl.UnknownFields
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *RemoveClientConnectionsReq) Reset() {
@@ -70,9 +70,9 @@ func (x *RemoveClientConnectionsReq) GetClientId() string {
}
type RemoveClientConnectionsRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RemoveClientConnectionsRes) Reset() {
@@ -106,11 +106,10 @@ func (*RemoveClientConnectionsRes) Descriptor() ([]byte, []int) {
}
type UnsetParentGroupFromChannelsReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
ParentGroupId string `protobuf:"bytes,1,opt,name=parent_group_id,json=parentGroupId,proto3" json:"parent_group_id,omitempty"`
unknownFields protoimpl.UnknownFields
ParentGroupId string `protobuf:"bytes,1,opt,name=parent_group_id,json=parentGroupId,proto3" json:"parent_group_id,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *UnsetParentGroupFromChannelsReq) Reset() {
@@ -151,9 +150,9 @@ func (x *UnsetParentGroupFromChannelsReq) GetParentGroupId() string {
}
type UnsetParentGroupFromChannelsRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnsetParentGroupFromChannelsRes) Reset() {
@@ -187,15 +186,14 @@ func (*UnsetParentGroupFromChannelsRes) Descriptor() ([]byte, []int) {
}
type AuthzReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
DomainId string `protobuf:"bytes,1,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
ClientType string `protobuf:"bytes,3,opt,name=client_type,json=clientType,proto3" json:"client_type,omitempty"`
ChannelId string `protobuf:"bytes,4,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
Type uint32 `protobuf:"varint,5,opt,name=type,proto3" json:"type,omitempty"`
unknownFields protoimpl.UnknownFields
DomainId string `protobuf:"bytes,1,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
ClientType string `protobuf:"bytes,3,opt,name=client_type,json=clientType,proto3" json:"client_type,omitempty"`
ChannelId string `protobuf:"bytes,4,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
Type uint32 `protobuf:"varint,5,opt,name=type,proto3" json:"type,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *AuthzReq) Reset() {
@@ -264,11 +262,10 @@ func (x *AuthzReq) GetType() uint32 {
}
type AuthzRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"`
unknownFields protoimpl.UnknownFields
Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *AuthzRes) Reset() {
@@ -310,75 +307,42 @@ func (x *AuthzRes) GetAuthorized() bool {
var File_channels_v1_channels_proto protoreflect.FileDescriptor
var file_channels_v1_channels_proto_rawDesc = []byte{
0x0a, 0x1a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x68,
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x63, 0x68,
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x16, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x22, 0x39, 0x0a, 0x1a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x12,
0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x1c, 0x0a, 0x1a,
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x22, 0x49, 0x0a, 0x1f, 0x55, 0x6e,
0x73, 0x65, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x72,
0x6f, 0x6d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x12, 0x26, 0x0a,
0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x72,
0x6f, 0x75, 0x70, 0x49, 0x64, 0x22, 0x21, 0x0a, 0x1f, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x50, 0x61,
0x72, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61,
0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x08, 0x41, 0x75, 0x74,
0x68, 0x7a, 0x52, 0x65, 0x71, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12,
0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65,
0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04,
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x64, 0x12,
0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74,
0x79, 0x70, 0x65, 0x22, 0x2a, 0x0a, 0x08, 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, 0x32,
0x8b, 0x03, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65,
0x12, 0x15, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41,
0x75, 0x74, 0x68, 0x7a, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65,
0x6c, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x7a, 0x52, 0x65, 0x73, 0x22, 0x00,
0x12, 0x6d, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x68,
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x52, 0x65, 0x71, 0x1a, 0x27, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e,
0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12,
0x7c, 0x0a, 0x1c, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x72,
0x6f, 0x75, 0x70, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12,
0x2c, 0x2e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e,
0x73, 0x65, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x72,
0x6f, 0x6d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x2c, 0x2e,
0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x65,
0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x72, 0x6f, 0x6d,
0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x4e, 0x0a,
0x0e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12,
0x1c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72,
0x69, 0x65, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e,
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65,
0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x22, 0x00, 0x42, 0x36, 0x5a,
0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x73, 0x6d,
0x61, 0x63, 0x68, 0x2f, 0x73, 0x75, 0x70, 0x65, 0x72, 0x6d, 0x71, 0x2f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65,
0x6c, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
const file_channels_v1_channels_proto_rawDesc = "" +
"\n" +
"\x1achannels/v1/channels.proto\x12\vchannels.v1\x1a\x16common/v1/common.proto\"9\n" +
"\x1aRemoveClientConnectionsReq\x12\x1b\n" +
"\tclient_id\x18\x01 \x01(\tR\bclientId\"\x1c\n" +
"\x1aRemoveClientConnectionsRes\"I\n" +
"\x1fUnsetParentGroupFromChannelsReq\x12&\n" +
"\x0fparent_group_id\x18\x01 \x01(\tR\rparentGroupId\"!\n" +
"\x1fUnsetParentGroupFromChannelsRes\"\x98\x01\n" +
"\bAuthzReq\x12\x1b\n" +
"\tdomain_id\x18\x01 \x01(\tR\bdomainId\x12\x1b\n" +
"\tclient_id\x18\x02 \x01(\tR\bclientId\x12\x1f\n" +
"\vclient_type\x18\x03 \x01(\tR\n" +
"clientType\x12\x1d\n" +
"\n" +
"channel_id\x18\x04 \x01(\tR\tchannelId\x12\x12\n" +
"\x04type\x18\x05 \x01(\rR\x04type\"*\n" +
"\bAuthzRes\x12\x1e\n" +
"\n" +
"authorized\x18\x01 \x01(\bR\n" +
"authorized2\xe1\x03\n" +
"\x0fChannelsService\x12;\n" +
"\tAuthorize\x12\x15.channels.v1.AuthzReq\x1a\x15.channels.v1.AuthzRes\"\x00\x12m\n" +
"\x17RemoveClientConnections\x12'.channels.v1.RemoveClientConnectionsReq\x1a'.channels.v1.RemoveClientConnectionsRes\"\x00\x12|\n" +
"\x1cUnsetParentGroupFromChannels\x12,.channels.v1.UnsetParentGroupFromChannelsReq\x1a,.channels.v1.UnsetParentGroupFromChannelsRes\"\x00\x12N\n" +
"\x0eRetrieveEntity\x12\x1c.common.v1.RetrieveEntityReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00\x12T\n" +
"\x11RetrieveIDByRoute\x12\x1f.common.v1.RetrieveIDByRouteReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00B1Z/github.com/absmach/supermq/api/grpc/channels/v1b\x06proto3"
var (
file_channels_v1_channels_proto_rawDescOnce sync.Once
file_channels_v1_channels_proto_rawDescData = file_channels_v1_channels_proto_rawDesc
file_channels_v1_channels_proto_rawDescData []byte
)
func file_channels_v1_channels_proto_rawDescGZIP() []byte {
file_channels_v1_channels_proto_rawDescOnce.Do(func() {
file_channels_v1_channels_proto_rawDescData = protoimpl.X.CompressGZIP(file_channels_v1_channels_proto_rawDescData)
file_channels_v1_channels_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_channels_v1_channels_proto_rawDesc), len(file_channels_v1_channels_proto_rawDesc)))
})
return file_channels_v1_channels_proto_rawDescData
}
@@ -392,19 +356,22 @@ var file_channels_v1_channels_proto_goTypes = []any{
(*AuthzReq)(nil), // 4: channels.v1.AuthzReq
(*AuthzRes)(nil), // 5: channels.v1.AuthzRes
(*v1.RetrieveEntityReq)(nil), // 6: common.v1.RetrieveEntityReq
(*v1.RetrieveEntityRes)(nil), // 7: common.v1.RetrieveEntityRes
(*v1.RetrieveIDByRouteReq)(nil), // 7: common.v1.RetrieveIDByRouteReq
(*v1.RetrieveEntityRes)(nil), // 8: common.v1.RetrieveEntityRes
}
var file_channels_v1_channels_proto_depIdxs = []int32{
4, // 0: channels.v1.ChannelsService.Authorize:input_type -> channels.v1.AuthzReq
0, // 1: channels.v1.ChannelsService.RemoveClientConnections:input_type -> channels.v1.RemoveClientConnectionsReq
2, // 2: channels.v1.ChannelsService.UnsetParentGroupFromChannels:input_type -> channels.v1.UnsetParentGroupFromChannelsReq
6, // 3: channels.v1.ChannelsService.RetrieveEntity:input_type -> common.v1.RetrieveEntityReq
5, // 4: channels.v1.ChannelsService.Authorize:output_type -> channels.v1.AuthzRes
1, // 5: channels.v1.ChannelsService.RemoveClientConnections:output_type -> channels.v1.RemoveClientConnectionsRes
3, // 6: channels.v1.ChannelsService.UnsetParentGroupFromChannels:output_type -> channels.v1.UnsetParentGroupFromChannelsRes
7, // 7: channels.v1.ChannelsService.RetrieveEntity:output_type -> common.v1.RetrieveEntityRes
4, // [4:8] is the sub-list for method output_type
0, // [0:4] is the sub-list for method input_type
7, // 4: channels.v1.ChannelsService.RetrieveIDByRoute:input_type -> common.v1.RetrieveIDByRouteReq
5, // 5: channels.v1.ChannelsService.Authorize:output_type -> channels.v1.AuthzRes
1, // 6: channels.v1.ChannelsService.RemoveClientConnections:output_type -> channels.v1.RemoveClientConnectionsRes
3, // 7: channels.v1.ChannelsService.UnsetParentGroupFromChannels:output_type -> channels.v1.UnsetParentGroupFromChannelsRes
8, // 8: channels.v1.ChannelsService.RetrieveEntity:output_type -> common.v1.RetrieveEntityRes
8, // 9: channels.v1.ChannelsService.RetrieveIDByRoute:output_type -> common.v1.RetrieveEntityRes
5, // [5:10] is the sub-list for method output_type
0, // [0:5] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -419,7 +386,7 @@ func file_channels_v1_channels_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_channels_v1_channels_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_channels_v1_channels_proto_rawDesc), len(file_channels_v1_channels_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
@@ -430,7 +397,6 @@ func file_channels_v1_channels_proto_init() {
MessageInfos: file_channels_v1_channels_proto_msgTypes,
}.Build()
File_channels_v1_channels_proto = out.File
file_channels_v1_channels_proto_rawDesc = nil
file_channels_v1_channels_proto_goTypes = nil
file_channels_v1_channels_proto_depIdxs = nil
}
@@ -4,14 +4,14 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.29.0
// - protoc v6.33.0
// source: channels/v1/channels.proto
package v1
import (
context "context"
v1 "github.com/absmach/supermq/internal/grpc/common/v1"
v1 "github.com/absmach/supermq/api/grpc/common/v1"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
@@ -27,6 +27,7 @@ const (
ChannelsService_RemoveClientConnections_FullMethodName = "/channels.v1.ChannelsService/RemoveClientConnections"
ChannelsService_UnsetParentGroupFromChannels_FullMethodName = "/channels.v1.ChannelsService/UnsetParentGroupFromChannels"
ChannelsService_RetrieveEntity_FullMethodName = "/channels.v1.ChannelsService/RetrieveEntity"
ChannelsService_RetrieveIDByRoute_FullMethodName = "/channels.v1.ChannelsService/RetrieveIDByRoute"
)
// ChannelsServiceClient is the client API for ChannelsService service.
@@ -37,6 +38,7 @@ type ChannelsServiceClient interface {
RemoveClientConnections(ctx context.Context, in *RemoveClientConnectionsReq, opts ...grpc.CallOption) (*RemoveClientConnectionsRes, error)
UnsetParentGroupFromChannels(ctx context.Context, in *UnsetParentGroupFromChannelsReq, opts ...grpc.CallOption) (*UnsetParentGroupFromChannelsRes, error)
RetrieveEntity(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
RetrieveIDByRoute(ctx context.Context, in *v1.RetrieveIDByRouteReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
}
type channelsServiceClient struct {
@@ -87,6 +89,16 @@ func (c *channelsServiceClient) RetrieveEntity(ctx context.Context, in *v1.Retri
return out, nil
}
func (c *channelsServiceClient) RetrieveIDByRoute(ctx context.Context, in *v1.RetrieveIDByRouteReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntityRes)
err := c.cc.Invoke(ctx, ChannelsService_RetrieveIDByRoute_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ChannelsServiceServer is the server API for ChannelsService service.
// All implementations must embed UnimplementedChannelsServiceServer
// for forward compatibility.
@@ -95,6 +107,7 @@ type ChannelsServiceServer interface {
RemoveClientConnections(context.Context, *RemoveClientConnectionsReq) (*RemoveClientConnectionsRes, error)
UnsetParentGroupFromChannels(context.Context, *UnsetParentGroupFromChannelsReq) (*UnsetParentGroupFromChannelsRes, error)
RetrieveEntity(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error)
RetrieveIDByRoute(context.Context, *v1.RetrieveIDByRouteReq) (*v1.RetrieveEntityRes, error)
mustEmbedUnimplementedChannelsServiceServer()
}
@@ -117,6 +130,9 @@ func (UnimplementedChannelsServiceServer) UnsetParentGroupFromChannels(context.C
func (UnimplementedChannelsServiceServer) RetrieveEntity(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method RetrieveEntity not implemented")
}
func (UnimplementedChannelsServiceServer) RetrieveIDByRoute(context.Context, *v1.RetrieveIDByRouteReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method RetrieveIDByRoute not implemented")
}
func (UnimplementedChannelsServiceServer) mustEmbedUnimplementedChannelsServiceServer() {}
func (UnimplementedChannelsServiceServer) testEmbeddedByValue() {}
@@ -210,6 +226,24 @@ func _ChannelsService_RetrieveEntity_Handler(srv interface{}, ctx context.Contex
return interceptor(ctx, in, info, handler)
}
func _ChannelsService_RetrieveIDByRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveIDByRouteReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ChannelsServiceServer).RetrieveIDByRoute(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ChannelsService_RetrieveIDByRoute_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ChannelsServiceServer).RetrieveIDByRoute(ctx, req.(*v1.RetrieveIDByRouteReq))
}
return interceptor(ctx, in, info, handler)
}
// ChannelsService_ServiceDesc is the grpc.ServiceDesc for ChannelsService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -233,6 +267,10 @@ var ChannelsService_ServiceDesc = grpc.ServiceDesc{
MethodName: "RetrieveEntity",
Handler: _ChannelsService_RetrieveEntity_Handler,
},
{
MethodName: "RetrieveIDByRoute",
Handler: _ChannelsService_RetrieveIDByRoute_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "channels/v1/channels.proto",
@@ -3,18 +3,19 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.2
// protoc v5.29.0
// protoc-gen-go v1.36.10
// protoc v6.33.0
// source: clients/v1/clients.proto
package v1
import (
v1 "github.com/absmach/supermq/internal/grpc/common/v1"
v1 "github.com/absmach/supermq/api/grpc/common/v1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -25,12 +26,10 @@ const (
)
type AuthnReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
unknownFields protoimpl.UnknownFields
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
ClientSecret string `protobuf:"bytes,2,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *AuthnReq) Reset() {
@@ -63,27 +62,19 @@ func (*AuthnReq) Descriptor() ([]byte, []int) {
return file_clients_v1_clients_proto_rawDescGZIP(), []int{0}
}
func (x *AuthnReq) GetClientId() string {
func (x *AuthnReq) GetToken() string {
if x != nil {
return x.ClientId
}
return ""
}
func (x *AuthnReq) GetClientSecret() string {
if x != nil {
return x.ClientSecret
return x.Token
}
return ""
}
type AuthnRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Authenticated bool `protobuf:"varint,1,opt,name=authenticated,proto3" json:"authenticated,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
Authenticated bool `protobuf:"varint,1,opt,name=authenticated,proto3" json:"authenticated,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *AuthnRes) Reset() {
@@ -131,11 +122,10 @@ func (x *AuthnRes) GetId() string {
}
type RemoveChannelConnectionsReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
ChannelId string `protobuf:"bytes,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
unknownFields protoimpl.UnknownFields
ChannelId string `protobuf:"bytes,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *RemoveChannelConnectionsReq) Reset() {
@@ -176,9 +166,9 @@ func (x *RemoveChannelConnectionsReq) GetChannelId() string {
}
type RemoveChannelConnectionsRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RemoveChannelConnectionsRes) Reset() {
@@ -212,11 +202,10 @@ func (*RemoveChannelConnectionsRes) Descriptor() ([]byte, []int) {
}
type UnsetParentGroupFromClientReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
ParentGroupId string `protobuf:"bytes,1,opt,name=parent_group_id,json=parentGroupId,proto3" json:"parent_group_id,omitempty"`
unknownFields protoimpl.UnknownFields
ParentGroupId string `protobuf:"bytes,1,opt,name=parent_group_id,json=parentGroupId,proto3" json:"parent_group_id,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *UnsetParentGroupFromClientReq) Reset() {
@@ -257,9 +246,9 @@ func (x *UnsetParentGroupFromClientReq) GetParentGroupId() string {
}
type UnsetParentGroupFromClientRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnsetParentGroupFromClientRes) Reset() {
@@ -294,87 +283,39 @@ func (*UnsetParentGroupFromClientRes) Descriptor() ([]byte, []int) {
var File_clients_v1_clients_proto protoreflect.FileDescriptor
var file_clients_v1_clients_proto_rawDesc = []byte{
0x0a, 0x18, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x63, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x1a, 0x16, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76,
0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4c,
0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c,
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63,
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0x40, 0x0a, 0x08,
0x41, 0x75, 0x74, 0x68, 0x6e, 0x52, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68,
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x0e,
0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x3c,
0x0a, 0x1b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x43,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, 0x22, 0x1d, 0x0a, 0x1b,
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e,
0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x22, 0x47, 0x0a, 0x1d, 0x55,
0x6e, 0x73, 0x65, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46,
0x72, 0x6f, 0x6d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x26, 0x0a, 0x0f,
0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f,
0x75, 0x70, 0x49, 0x64, 0x22, 0x1f, 0x0a, 0x1d, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x50, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x52, 0x65, 0x73, 0x32, 0x83, 0x05, 0x0a, 0x0e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68,
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e,
0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14,
0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68,
0x6e, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65,
0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74,
0x79, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x10, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65,
0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45,
0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45,
0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0e,
0x41, 0x64, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x6f,
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x11,
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65,
0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
0x65, 0x71, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x6e, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43,
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x27, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52,
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x27, 0x2e, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68,
0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x1a, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x50, 0x61,
0x72, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x12, 0x29, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x55, 0x6e, 0x73, 0x65, 0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75,
0x70, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x29,
0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x73, 0x65,
0x74, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x46, 0x72, 0x6f, 0x6d,
0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x22, 0x00, 0x42, 0x35, 0x5a, 0x33, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x73, 0x6d, 0x61, 0x63,
0x68, 0x2f, 0x73, 0x75, 0x70, 0x65, 0x72, 0x6d, 0x71, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2f,
0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
const file_clients_v1_clients_proto_rawDesc = "" +
"\n" +
"\x18clients/v1/clients.proto\x12\n" +
"clients.v1\x1a\x16common/v1/common.proto\" \n" +
"\bAuthnReq\x12\x14\n" +
"\x05token\x18\x01 \x01(\tR\x05token\"@\n" +
"\bAuthnRes\x12$\n" +
"\rauthenticated\x18\x01 \x01(\bR\rauthenticated\x12\x0e\n" +
"\x02id\x18\x02 \x01(\tR\x02id\"<\n" +
"\x1bRemoveChannelConnectionsReq\x12\x1d\n" +
"\n" +
"channel_id\x18\x01 \x01(\tR\tchannelId\"\x1d\n" +
"\x1bRemoveChannelConnectionsRes\"G\n" +
"\x1dUnsetParentGroupFromClientReq\x12&\n" +
"\x0fparent_group_id\x18\x01 \x01(\tR\rparentGroupId\"\x1f\n" +
"\x1dUnsetParentGroupFromClientRes2\x83\x05\n" +
"\x0eClientsService\x12<\n" +
"\fAuthenticate\x12\x14.clients.v1.AuthnReq\x1a\x14.clients.v1.AuthnRes\"\x00\x12N\n" +
"\x0eRetrieveEntity\x12\x1c.common.v1.RetrieveEntityReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00\x12T\n" +
"\x10RetrieveEntities\x12\x1e.common.v1.RetrieveEntitiesReq\x1a\x1e.common.v1.RetrieveEntitiesRes\"\x00\x12N\n" +
"\x0eAddConnections\x12\x1c.common.v1.AddConnectionsReq\x1a\x1c.common.v1.AddConnectionsRes\"\x00\x12W\n" +
"\x11RemoveConnections\x12\x1f.common.v1.RemoveConnectionsReq\x1a\x1f.common.v1.RemoveConnectionsRes\"\x00\x12n\n" +
"\x18RemoveChannelConnections\x12'.clients.v1.RemoveChannelConnectionsReq\x1a'.clients.v1.RemoveChannelConnectionsRes\"\x00\x12t\n" +
"\x1aUnsetParentGroupFromClient\x12).clients.v1.UnsetParentGroupFromClientReq\x1a).clients.v1.UnsetParentGroupFromClientRes\"\x00B0Z.github.com/absmach/supermq/api/grpc/clients/v1b\x06proto3"
var (
file_clients_v1_clients_proto_rawDescOnce sync.Once
file_clients_v1_clients_proto_rawDescData = file_clients_v1_clients_proto_rawDesc
file_clients_v1_clients_proto_rawDescData []byte
)
func file_clients_v1_clients_proto_rawDescGZIP() []byte {
file_clients_v1_clients_proto_rawDescOnce.Do(func() {
file_clients_v1_clients_proto_rawDescData = protoimpl.X.CompressGZIP(file_clients_v1_clients_proto_rawDescData)
file_clients_v1_clients_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_clients_v1_clients_proto_rawDesc), len(file_clients_v1_clients_proto_rawDesc)))
})
return file_clients_v1_clients_proto_rawDescData
}
@@ -427,7 +368,7 @@ func file_clients_v1_clients_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_clients_v1_clients_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_clients_v1_clients_proto_rawDesc), len(file_clients_v1_clients_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
@@ -438,7 +379,6 @@ func file_clients_v1_clients_proto_init() {
MessageInfos: file_clients_v1_clients_proto_msgTypes,
}.Build()
File_clients_v1_clients_proto = out.File
file_clients_v1_clients_proto_rawDesc = nil
file_clients_v1_clients_proto_goTypes = nil
file_clients_v1_clients_proto_depIdxs = nil
}
@@ -4,14 +4,14 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.29.0
// - protoc v6.33.0
// source: clients/v1/clients.proto
package v1
import (
context "context"
v1 "github.com/absmach/supermq/internal/grpc/common/v1"
v1 "github.com/absmach/supermq/api/grpc/common/v1"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
@@ -3,8 +3,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.2
// protoc v5.29.0
// protoc-gen-go v1.36.10
// protoc v6.33.0
// source: common/v1/common.proto
package v1
@@ -14,6 +14,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -24,11 +25,10 @@ const (
)
type RetrieveEntitiesReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"`
unknownFields protoimpl.UnknownFields
Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *RetrieveEntitiesReq) Reset() {
@@ -69,14 +69,13 @@ func (x *RetrieveEntitiesReq) GetIds() []string {
}
type RetrieveEntitiesRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"`
Limit uint64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"`
Offset uint64 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"`
Entities []*EntityBasic `protobuf:"bytes,4,rep,name=entities,proto3" json:"entities,omitempty"`
unknownFields protoimpl.UnknownFields
Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"`
Limit uint64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"`
Offset uint64 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"`
Entities []*EntityBasic `protobuf:"bytes,4,rep,name=entities,proto3" json:"entities,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *RetrieveEntitiesRes) Reset() {
@@ -138,11 +137,10 @@ func (x *RetrieveEntitiesRes) GetEntities() []*EntityBasic {
}
type RetrieveEntityReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *RetrieveEntityReq) Reset() {
@@ -183,11 +181,10 @@ func (x *RetrieveEntityReq) GetId() string {
}
type RetrieveEntityRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Entity *EntityBasic `protobuf:"bytes,1,opt,name=entity,proto3" json:"entity,omitempty"`
unknownFields protoimpl.UnknownFields
Entity *EntityBasic `protobuf:"bytes,1,opt,name=entity,proto3" json:"entity,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *RetrieveEntityRes) Reset() {
@@ -228,14 +225,13 @@ func (x *RetrieveEntityRes) GetEntity() *EntityBasic {
}
type EntityBasic struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
DomainId string `protobuf:"bytes,2,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
ParentGroupId string `protobuf:"bytes,3,opt,name=parent_group_id,json=parentGroupId,proto3" json:"parent_group_id,omitempty"`
Status uint32 `protobuf:"varint,4,opt,name=status,proto3" json:"status,omitempty"`
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
DomainId string `protobuf:"bytes,2,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
ParentGroupId string `protobuf:"bytes,3,opt,name=parent_group_id,json=parentGroupId,proto3" json:"parent_group_id,omitempty"`
Status uint32 `protobuf:"varint,4,opt,name=status,proto3" json:"status,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *EntityBasic) Reset() {
@@ -297,11 +293,10 @@ func (x *EntityBasic) GetStatus() uint32 {
}
type AddConnectionsReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Connections []*Connection `protobuf:"bytes,1,rep,name=connections,proto3" json:"connections,omitempty"`
unknownFields protoimpl.UnknownFields
Connections []*Connection `protobuf:"bytes,1,rep,name=connections,proto3" json:"connections,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *AddConnectionsReq) Reset() {
@@ -342,11 +337,10 @@ func (x *AddConnectionsReq) GetConnections() []*Connection {
}
type AddConnectionsRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
unknownFields protoimpl.UnknownFields
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *AddConnectionsRes) Reset() {
@@ -387,11 +381,10 @@ func (x *AddConnectionsRes) GetOk() bool {
}
type RemoveConnectionsReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Connections []*Connection `protobuf:"bytes,1,rep,name=connections,proto3" json:"connections,omitempty"`
unknownFields protoimpl.UnknownFields
Connections []*Connection `protobuf:"bytes,1,rep,name=connections,proto3" json:"connections,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *RemoveConnectionsReq) Reset() {
@@ -432,11 +425,10 @@ func (x *RemoveConnectionsReq) GetConnections() []*Connection {
}
type RemoveConnectionsRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
unknownFields protoimpl.UnknownFields
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *RemoveConnectionsRes) Reset() {
@@ -477,14 +469,13 @@ func (x *RemoveConnectionsRes) GetOk() bool {
}
type Connection struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
DomainId string `protobuf:"bytes,3,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
Type uint32 `protobuf:"varint,4,opt,name=type,proto3" json:"type,omitempty"`
unknownFields protoimpl.UnknownFields
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
DomainId string `protobuf:"bytes,3,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
Type uint32 `protobuf:"varint,4,opt,name=type,proto3" json:"type,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *Connection) Reset() {
@@ -545,79 +536,111 @@ func (x *Connection) GetType() uint32 {
return 0
}
type RetrieveIDByRouteReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Route string `protobuf:"bytes,1,opt,name=route,proto3" json:"route,omitempty"`
DomainId string `protobuf:"bytes,2,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RetrieveIDByRouteReq) Reset() {
*x = RetrieveIDByRouteReq{}
mi := &file_common_v1_common_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RetrieveIDByRouteReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RetrieveIDByRouteReq) ProtoMessage() {}
func (x *RetrieveIDByRouteReq) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RetrieveIDByRouteReq.ProtoReflect.Descriptor instead.
func (*RetrieveIDByRouteReq) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{10}
}
func (x *RetrieveIDByRouteReq) GetRoute() string {
if x != nil {
return x.Route
}
return ""
}
func (x *RetrieveIDByRouteReq) GetDomainId() string {
if x != nil {
return x.DomainId
}
return ""
}
var File_common_v1_common_proto protoreflect.FileDescriptor
var file_common_v1_common_proto_rawDesc = []byte{
0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x2e, 0x76, 0x31, 0x22, 0x27, 0x0a, 0x13, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45,
0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64,
0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0x8d, 0x01, 0x0a,
0x13, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65,
0x73, 0x52, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69,
0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74,
0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x32, 0x0a, 0x08, 0x65, 0x6e, 0x74, 0x69,
0x74, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x42, 0x61, 0x73,
0x69, 0x63, 0x52, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x23, 0x0a, 0x11,
0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65,
0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x64, 0x22, 0x43, 0x0a, 0x11, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x06,
0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x7a, 0x0a, 0x0b, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79,
0x42, 0x61, 0x73, 0x69, 0x63, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x67, 0x72, 0x6f,
0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74,
0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
0x75, 0x73, 0x22, 0x4c, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x12, 0x37, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x22, 0x23, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x73, 0x52, 0x65, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
0x08, 0x52, 0x02, 0x6f, 0x6b, 0x22, 0x4f, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x12, 0x37, 0x0a,
0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43,
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x26, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x12, 0x0e,
0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, 0x6f, 0x6b, 0x22, 0x79,
0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61,
0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63,
0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 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, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x73, 0x6d, 0x61, 0x63, 0x68, 0x2f,
0x73, 0x75, 0x70, 0x65, 0x72, 0x6d, 0x71, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
const file_common_v1_common_proto_rawDesc = "" +
"\n" +
"\x16common/v1/common.proto\x12\tcommon.v1\"'\n" +
"\x13RetrieveEntitiesReq\x12\x10\n" +
"\x03ids\x18\x01 \x03(\tR\x03ids\"\x8d\x01\n" +
"\x13RetrieveEntitiesRes\x12\x14\n" +
"\x05total\x18\x01 \x01(\x04R\x05total\x12\x14\n" +
"\x05limit\x18\x02 \x01(\x04R\x05limit\x12\x16\n" +
"\x06offset\x18\x03 \x01(\x04R\x06offset\x122\n" +
"\bentities\x18\x04 \x03(\v2\x16.common.v1.EntityBasicR\bentities\"#\n" +
"\x11RetrieveEntityReq\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"C\n" +
"\x11RetrieveEntityRes\x12.\n" +
"\x06entity\x18\x01 \x01(\v2\x16.common.v1.EntityBasicR\x06entity\"z\n" +
"\vEntityBasic\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x1b\n" +
"\tdomain_id\x18\x02 \x01(\tR\bdomainId\x12&\n" +
"\x0fparent_group_id\x18\x03 \x01(\tR\rparentGroupId\x12\x16\n" +
"\x06status\x18\x04 \x01(\rR\x06status\"L\n" +
"\x11AddConnectionsReq\x127\n" +
"\vconnections\x18\x01 \x03(\v2\x15.common.v1.ConnectionR\vconnections\"#\n" +
"\x11AddConnectionsRes\x12\x0e\n" +
"\x02ok\x18\x01 \x01(\bR\x02ok\"O\n" +
"\x14RemoveConnectionsReq\x127\n" +
"\vconnections\x18\x01 \x03(\v2\x15.common.v1.ConnectionR\vconnections\"&\n" +
"\x14RemoveConnectionsRes\x12\x0e\n" +
"\x02ok\x18\x01 \x01(\bR\x02ok\"y\n" +
"\n" +
"Connection\x12\x1b\n" +
"\tclient_id\x18\x01 \x01(\tR\bclientId\x12\x1d\n" +
"\n" +
"channel_id\x18\x02 \x01(\tR\tchannelId\x12\x1b\n" +
"\tdomain_id\x18\x03 \x01(\tR\bdomainId\x12\x12\n" +
"\x04type\x18\x04 \x01(\rR\x04type\"I\n" +
"\x14RetrieveIDByRouteReq\x12\x14\n" +
"\x05route\x18\x01 \x01(\tR\x05route\x12\x1b\n" +
"\tdomain_id\x18\x02 \x01(\tR\bdomainIdB/Z-github.com/absmach/supermq/api/grpc/common/v1b\x06proto3"
var (
file_common_v1_common_proto_rawDescOnce sync.Once
file_common_v1_common_proto_rawDescData = file_common_v1_common_proto_rawDesc
file_common_v1_common_proto_rawDescData []byte
)
func file_common_v1_common_proto_rawDescGZIP() []byte {
file_common_v1_common_proto_rawDescOnce.Do(func() {
file_common_v1_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_v1_common_proto_rawDescData)
file_common_v1_common_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_common_v1_common_proto_rawDesc), len(file_common_v1_common_proto_rawDesc)))
})
return file_common_v1_common_proto_rawDescData
}
var file_common_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
var file_common_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_common_v1_common_proto_goTypes = []any{
(*RetrieveEntitiesReq)(nil), // 0: common.v1.RetrieveEntitiesReq
(*RetrieveEntitiesRes)(nil), // 1: common.v1.RetrieveEntitiesRes
@@ -629,6 +652,7 @@ var file_common_v1_common_proto_goTypes = []any{
(*RemoveConnectionsReq)(nil), // 7: common.v1.RemoveConnectionsReq
(*RemoveConnectionsRes)(nil), // 8: common.v1.RemoveConnectionsRes
(*Connection)(nil), // 9: common.v1.Connection
(*RetrieveIDByRouteReq)(nil), // 10: common.v1.RetrieveIDByRouteReq
}
var file_common_v1_common_proto_depIdxs = []int32{
4, // 0: common.v1.RetrieveEntitiesRes.entities:type_name -> common.v1.EntityBasic
@@ -651,9 +675,9 @@ func file_common_v1_common_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_common_v1_common_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_v1_common_proto_rawDesc), len(file_common_v1_common_proto_rawDesc)),
NumEnums: 0,
NumMessages: 10,
NumMessages: 11,
NumExtensions: 0,
NumServices: 0,
},
@@ -662,7 +686,6 @@ func file_common_v1_common_proto_init() {
MessageInfos: file_common_v1_common_proto_msgTypes,
}.Build()
File_common_v1_common_proto = out.File
file_common_v1_common_proto_rawDesc = nil
file_common_v1_common_proto_goTypes = nil
file_common_v1_common_proto_depIdxs = nil
}
@@ -3,17 +3,19 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.2
// protoc v5.29.0
// protoc-gen-go v1.36.10
// protoc v6.33.0
// source: domains/v1/domains.proto
package v1
import (
v1 "github.com/absmach/supermq/api/grpc/common/v1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -24,11 +26,10 @@ const (
)
type DeleteUserRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"`
unknownFields protoimpl.UnknownFields
Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *DeleteUserRes) Reset() {
@@ -69,11 +70,10 @@ func (x *DeleteUserRes) GetDeleted() bool {
}
type DeleteUserReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *DeleteUserReq) Reset() {
@@ -115,49 +115,48 @@ func (x *DeleteUserReq) GetId() string {
var File_domains_v1_domains_proto protoreflect.FileDescriptor
var file_domains_v1_domains_proto_rawDesc = []byte{
0x0a, 0x18, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x6f, 0x6d,
0x61, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x64, 0x6f, 0x6d, 0x61,
0x69, 0x6e, 0x73, 0x2e, 0x76, 0x31, 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, 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,
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69,
0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72,
0x52, 0x65, 0x73, 0x22, 0x00, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x73, 0x6d, 0x61, 0x63, 0x68, 0x2f, 0x73, 0x75, 0x70, 0x65,
0x72, 0x6d, 0x71, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70,
0x63, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
const file_domains_v1_domains_proto_rawDesc = "" +
"\n" +
"\x18domains/v1/domains.proto\x12\n" +
"domains.v1\x1a\x16common/v1/common.proto\")\n" +
"\rDeleteUserRes\x12\x18\n" +
"\adeleted\x18\x01 \x01(\bR\adeleted\"\x1f\n" +
"\rDeleteUserReq\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id2\x87\x02\n" +
"\x0eDomainsService\x12O\n" +
"\x15DeleteUserFromDomains\x12\x19.domains.v1.DeleteUserReq\x1a\x19.domains.v1.DeleteUserRes\"\x00\x12N\n" +
"\x0eRetrieveStatus\x12\x1c.common.v1.RetrieveEntityReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00\x12T\n" +
"\x11RetrieveIDByRoute\x12\x1f.common.v1.RetrieveIDByRouteReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00B5Z3github.com/absmach/supermq/internal/grpc/domains/v1b\x06proto3"
var (
file_domains_v1_domains_proto_rawDescOnce sync.Once
file_domains_v1_domains_proto_rawDescData = file_domains_v1_domains_proto_rawDesc
file_domains_v1_domains_proto_rawDescData []byte
)
func file_domains_v1_domains_proto_rawDescGZIP() []byte {
file_domains_v1_domains_proto_rawDescOnce.Do(func() {
file_domains_v1_domains_proto_rawDescData = protoimpl.X.CompressGZIP(file_domains_v1_domains_proto_rawDescData)
file_domains_v1_domains_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_domains_v1_domains_proto_rawDesc), len(file_domains_v1_domains_proto_rawDesc)))
})
return file_domains_v1_domains_proto_rawDescData
}
var file_domains_v1_domains_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_domains_v1_domains_proto_goTypes = []any{
(*DeleteUserRes)(nil), // 0: domains.v1.DeleteUserRes
(*DeleteUserReq)(nil), // 1: domains.v1.DeleteUserReq
(*DeleteUserRes)(nil), // 0: domains.v1.DeleteUserRes
(*DeleteUserReq)(nil), // 1: domains.v1.DeleteUserReq
(*v1.RetrieveEntityReq)(nil), // 2: common.v1.RetrieveEntityReq
(*v1.RetrieveIDByRouteReq)(nil), // 3: common.v1.RetrieveIDByRouteReq
(*v1.RetrieveEntityRes)(nil), // 4: common.v1.RetrieveEntityRes
}
var file_domains_v1_domains_proto_depIdxs = []int32{
1, // 0: domains.v1.DomainsService.DeleteUserFromDomains:input_type -> domains.v1.DeleteUserReq
0, // 1: domains.v1.DomainsService.DeleteUserFromDomains:output_type -> domains.v1.DeleteUserRes
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
2, // 1: domains.v1.DomainsService.RetrieveStatus:input_type -> common.v1.RetrieveEntityReq
3, // 2: domains.v1.DomainsService.RetrieveIDByRoute:input_type -> common.v1.RetrieveIDByRouteReq
0, // 3: domains.v1.DomainsService.DeleteUserFromDomains:output_type -> domains.v1.DeleteUserRes
4, // 4: domains.v1.DomainsService.RetrieveStatus:output_type -> common.v1.RetrieveEntityRes
4, // 5: domains.v1.DomainsService.RetrieveIDByRoute:output_type -> common.v1.RetrieveEntityRes
3, // [3:6] is the sub-list for method output_type
0, // [0:3] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@@ -172,7 +171,7 @@ func file_domains_v1_domains_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_domains_v1_domains_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_domains_v1_domains_proto_rawDesc), len(file_domains_v1_domains_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
@@ -183,7 +182,6 @@ func file_domains_v1_domains_proto_init() {
MessageInfos: file_domains_v1_domains_proto_msgTypes,
}.Build()
File_domains_v1_domains_proto = out.File
file_domains_v1_domains_proto_rawDesc = nil
file_domains_v1_domains_proto_goTypes = nil
file_domains_v1_domains_proto_depIdxs = nil
}
@@ -4,13 +4,14 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.29.0
// - protoc v6.33.0
// source: domains/v1/domains.proto
package v1
import (
context "context"
v1 "github.com/absmach/supermq/api/grpc/common/v1"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
@@ -23,6 +24,8 @@ const _ = grpc.SupportPackageIsVersion9
const (
DomainsService_DeleteUserFromDomains_FullMethodName = "/domains.v1.DomainsService/DeleteUserFromDomains"
DomainsService_RetrieveStatus_FullMethodName = "/domains.v1.DomainsService/RetrieveStatus"
DomainsService_RetrieveIDByRoute_FullMethodName = "/domains.v1.DomainsService/RetrieveIDByRoute"
)
// DomainsServiceClient is the client API for DomainsService service.
@@ -33,6 +36,8 @@ const (
// domains functionalities for SuperMQ services.
type DomainsServiceClient interface {
DeleteUserFromDomains(ctx context.Context, in *DeleteUserReq, opts ...grpc.CallOption) (*DeleteUserRes, error)
RetrieveStatus(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
RetrieveIDByRoute(ctx context.Context, in *v1.RetrieveIDByRouteReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
}
type domainsServiceClient struct {
@@ -53,6 +58,26 @@ func (c *domainsServiceClient) DeleteUserFromDomains(ctx context.Context, in *De
return out, nil
}
func (c *domainsServiceClient) RetrieveStatus(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntityRes)
err := c.cc.Invoke(ctx, DomainsService_RetrieveStatus_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *domainsServiceClient) RetrieveIDByRoute(ctx context.Context, in *v1.RetrieveIDByRouteReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntityRes)
err := c.cc.Invoke(ctx, DomainsService_RetrieveIDByRoute_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// DomainsServiceServer is the server API for DomainsService service.
// All implementations must embed UnimplementedDomainsServiceServer
// for forward compatibility.
@@ -61,6 +86,8 @@ func (c *domainsServiceClient) DeleteUserFromDomains(ctx context.Context, in *De
// domains functionalities for SuperMQ services.
type DomainsServiceServer interface {
DeleteUserFromDomains(context.Context, *DeleteUserReq) (*DeleteUserRes, error)
RetrieveStatus(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error)
RetrieveIDByRoute(context.Context, *v1.RetrieveIDByRouteReq) (*v1.RetrieveEntityRes, error)
mustEmbedUnimplementedDomainsServiceServer()
}
@@ -74,6 +101,12 @@ type UnimplementedDomainsServiceServer struct{}
func (UnimplementedDomainsServiceServer) DeleteUserFromDomains(context.Context, *DeleteUserReq) (*DeleteUserRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteUserFromDomains not implemented")
}
func (UnimplementedDomainsServiceServer) RetrieveStatus(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method RetrieveStatus not implemented")
}
func (UnimplementedDomainsServiceServer) RetrieveIDByRoute(context.Context, *v1.RetrieveIDByRouteReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Errorf(codes.Unimplemented, "method RetrieveIDByRoute not implemented")
}
func (UnimplementedDomainsServiceServer) mustEmbedUnimplementedDomainsServiceServer() {}
func (UnimplementedDomainsServiceServer) testEmbeddedByValue() {}
@@ -113,6 +146,42 @@ func _DomainsService_DeleteUserFromDomains_Handler(srv interface{}, ctx context.
return interceptor(ctx, in, info, handler)
}
func _DomainsService_RetrieveStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveEntityReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainsServiceServer).RetrieveStatus(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: DomainsService_RetrieveStatus_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainsServiceServer).RetrieveStatus(ctx, req.(*v1.RetrieveEntityReq))
}
return interceptor(ctx, in, info, handler)
}
func _DomainsService_RetrieveIDByRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveIDByRouteReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainsServiceServer).RetrieveIDByRoute(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: DomainsService_RetrieveIDByRoute_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainsServiceServer).RetrieveIDByRoute(ctx, req.(*v1.RetrieveIDByRouteReq))
}
return interceptor(ctx, in, info, handler)
}
// DomainsService_ServiceDesc is the grpc.ServiceDesc for DomainsService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -124,6 +193,14 @@ var DomainsService_ServiceDesc = grpc.ServiceDesc{
MethodName: "DeleteUserFromDomains",
Handler: _DomainsService_DeleteUserFromDomains_Handler,
},
{
MethodName: "RetrieveStatus",
Handler: _DomainsService_RetrieveStatus_Handler,
},
{
MethodName: "RetrieveIDByRoute",
Handler: _DomainsService_RetrieveIDByRoute_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "domains/v1/domains.proto",
@@ -3,17 +3,18 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.2
// protoc v5.29.0
// protoc-gen-go v1.36.10
// protoc v6.33.0
// source: groups/v1/groups.proto
package v1
import (
v1 "github.com/absmach/supermq/internal/grpc/common/v1"
v1 "github.com/absmach/supermq/api/grpc/common/v1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
unsafe "unsafe"
)
const (
@@ -25,22 +26,11 @@ const (
var File_groups_v1_groups_proto protoreflect.FileDescriptor
var file_groups_v1_groups_proto_rawDesc = []byte{
0x0a, 0x16, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x72, 0x6f, 0x75,
0x70, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73,
0x2e, 0x76, 0x31, 0x1a, 0x16, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x5f, 0x0a, 0x0d, 0x47,
0x72, 0x6f, 0x75, 0x70, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4e, 0x0a, 0x0e,
0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1c,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69,
0x65, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76,
0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x22, 0x00, 0x42, 0x34, 0x5a, 0x32,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x73, 0x6d, 0x61,
0x63, 0x68, 0x2f, 0x73, 0x75, 0x70, 0x65, 0x72, 0x6d, 0x71, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f,
0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
const file_groups_v1_groups_proto_rawDesc = "" +
"\n" +
"\x16groups/v1/groups.proto\x12\tgroups.v1\x1a\x16common/v1/common.proto2_\n" +
"\rGroupsService\x12N\n" +
"\x0eRetrieveEntity\x12\x1c.common.v1.RetrieveEntityReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00B/Z-github.com/absmach/supermq/api/grpc/groups/v1b\x06proto3"
var file_groups_v1_groups_proto_goTypes = []any{
(*v1.RetrieveEntityReq)(nil), // 0: common.v1.RetrieveEntityReq
@@ -65,7 +55,7 @@ func file_groups_v1_groups_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_groups_v1_groups_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_groups_v1_groups_proto_rawDesc), len(file_groups_v1_groups_proto_rawDesc)),
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
@@ -75,7 +65,6 @@ func file_groups_v1_groups_proto_init() {
DependencyIndexes: file_groups_v1_groups_proto_depIdxs,
}.Build()
File_groups_v1_groups_proto = out.File
file_groups_v1_groups_proto_rawDesc = nil
file_groups_v1_groups_proto_goTypes = nil
file_groups_v1_groups_proto_depIdxs = nil
}
@@ -4,14 +4,14 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.29.0
// - protoc v6.33.0
// source: groups/v1/groups.proto
package v1
import (
context "context"
v1 "github.com/absmach/supermq/internal/grpc/common/v1"
v1 "github.com/absmach/supermq/api/grpc/common/v1"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
@@ -3,8 +3,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.35.2
// protoc v5.29.0
// protoc-gen-go v1.36.10
// protoc v6.33.0
// source: token/v1/token.proto
package v1
@@ -14,6 +14,7 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -24,12 +25,13 @@ const (
)
type IssueReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
state protoimpl.MessageState `protogen:"open.v1"`
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
UserRole uint32 `protobuf:"varint,2,opt,name=user_role,json=userRole,proto3" json:"user_role,omitempty"`
Type uint32 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"`
Verified bool `protobuf:"varint,4,opt,name=verified,proto3" json:"verified,omitempty"`
unknownFields protoimpl.UnknownFields
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
Type uint32 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"`
sizeCache protoimpl.SizeCache
}
func (x *IssueReq) Reset() {
@@ -69,6 +71,13 @@ func (x *IssueReq) GetUserId() string {
return ""
}
func (x *IssueReq) GetUserRole() uint32 {
if x != nil {
return x.UserRole
}
return 0
}
func (x *IssueReq) GetType() uint32 {
if x != nil {
return x.Type
@@ -76,12 +85,19 @@ func (x *IssueReq) GetType() uint32 {
return 0
}
type RefreshReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
func (x *IssueReq) GetVerified() bool {
if x != nil {
return x.Verified
}
return false
}
RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
type RefreshReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
Verified bool `protobuf:"varint,2,opt,name=verified,proto3" json:"verified,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RefreshReq) Reset() {
@@ -121,17 +137,23 @@ func (x *RefreshReq) GetRefreshToken() string {
return ""
}
func (x *RefreshReq) GetVerified() bool {
if x != nil {
return x.Verified
}
return false
}
// 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
state protoimpl.MessageState `protogen:"open.v1"`
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
RefreshToken *string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3,oneof" json:"refresh_token,omitempty"`
AccessType string `protobuf:"bytes,3,opt,name=access_type,json=accessType,proto3" json:"access_type,omitempty"`
unknownFields protoimpl.UnknownFields
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"`
sizeCache protoimpl.SizeCache
}
func (x *Token) Reset() {
@@ -187,46 +209,36 @@ func (x *Token) GetAccessType() string {
var File_token_v1_token_proto protoreflect.FileDescriptor
var file_token_v1_token_proto_rawDesc = []byte{
0x0a, 0x14, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x76, 0x31,
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, 0x03, 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, 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, 0x32, 0x72, 0x0a, 0x0c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12,
0x12, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65,
0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x54,
0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x00, 0x12, 0x32, 0x0a, 0x07, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73,
0x68, 0x12, 0x14, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x66,
0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e,
0x76, 0x31, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x00, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x62, 0x73, 0x6d, 0x61, 0x63, 0x68,
0x2f, 0x73, 0x75, 0x70, 0x65, 0x72, 0x6d, 0x71, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2f, 0x76, 0x31, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
const file_token_v1_token_proto_rawDesc = "" +
"\n" +
"\x14token/v1/token.proto\x12\btoken.v1\"p\n" +
"\bIssueReq\x12\x17\n" +
"\auser_id\x18\x01 \x01(\tR\x06userId\x12\x1b\n" +
"\tuser_role\x18\x02 \x01(\rR\buserRole\x12\x12\n" +
"\x04type\x18\x03 \x01(\rR\x04type\x12\x1a\n" +
"\bverified\x18\x04 \x01(\bR\bverified\"M\n" +
"\n" +
"RefreshReq\x12#\n" +
"\rrefresh_token\x18\x01 \x01(\tR\frefreshToken\x12\x1a\n" +
"\bverified\x18\x02 \x01(\bR\bverified\"\x87\x01\n" +
"\x05Token\x12!\n" +
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12(\n" +
"\rrefresh_token\x18\x02 \x01(\tH\x00R\frefreshToken\x88\x01\x01\x12\x1f\n" +
"\vaccess_type\x18\x03 \x01(\tR\n" +
"accessTypeB\x10\n" +
"\x0e_refresh_token2r\n" +
"\fTokenService\x12.\n" +
"\x05Issue\x12\x12.token.v1.IssueReq\x1a\x0f.token.v1.Token\"\x00\x122\n" +
"\aRefresh\x12\x14.token.v1.RefreshReq\x1a\x0f.token.v1.Token\"\x00B.Z,github.com/absmach/supermq/api/grpc/token/v1b\x06proto3"
var (
file_token_v1_token_proto_rawDescOnce sync.Once
file_token_v1_token_proto_rawDescData = file_token_v1_token_proto_rawDesc
file_token_v1_token_proto_rawDescData []byte
)
func file_token_v1_token_proto_rawDescGZIP() []byte {
file_token_v1_token_proto_rawDescOnce.Do(func() {
file_token_v1_token_proto_rawDescData = protoimpl.X.CompressGZIP(file_token_v1_token_proto_rawDescData)
file_token_v1_token_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_token_v1_token_proto_rawDesc), len(file_token_v1_token_proto_rawDesc)))
})
return file_token_v1_token_proto_rawDescData
}
@@ -259,7 +271,7 @@ func file_token_v1_token_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_token_v1_token_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_token_v1_token_proto_rawDesc), len(file_token_v1_token_proto_rawDesc)),
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
@@ -270,7 +282,6 @@ func file_token_v1_token_proto_init() {
MessageInfos: file_token_v1_token_proto_msgTypes,
}.Build()
File_token_v1_token_proto = out.File
file_token_v1_token_proto_rawDesc = nil
file_token_v1_token_proto_goTypes = nil
file_token_v1_token_proto_depIdxs = nil
}
@@ -4,7 +4,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.29.0
// - protoc v6.33.0
// source: token/v1/token.proto
package v1
+157 -75
View File
@@ -1,19 +1,20 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
package http
import (
"context"
"encoding/json"
"net/http"
"net/mail"
"regexp"
"strings"
"github.com/absmach/supermq"
"github.com/absmach/supermq/bootstrap"
"github.com/absmach/supermq/certs"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/clients"
"github.com/absmach/supermq/groups"
"github.com/absmach/supermq/pkg/apiutil"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/absmach/supermq/users"
@@ -21,61 +22,68 @@ import (
)
const (
MemberKindKey = "member_kind"
PermissionKey = "permission"
RelationKey = "relation"
StatusKey = "status"
OffsetKey = "offset"
OrderKey = "order"
LimitKey = "limit"
MetadataKey = "metadata"
ParentKey = "parent_id"
OwnerKey = "owner_id"
ClientKey = "client"
UsernameKey = "username"
NameKey = "name"
GroupKey = "group"
ActionKey = "action"
ActionsKey = "actions"
RoleIDKey = "role_id"
RoleNameKey = "role_name"
AccessTypeKey = "access_type"
TagKey = "tag"
FirstNameKey = "first_name"
LastNameKey = "last_name"
TotalKey = "total"
SubjectKey = "subject"
ObjectKey = "object"
LevelKey = "level"
StartLevelKey = "start_level"
EndLevelKey = "end_level"
TreeKey = "tree"
DirKey = "dir"
ListPerms = "list_perms"
VisibilityKey = "visibility"
EmailKey = "email"
SharedByKey = "shared_by"
TokenKey = "token"
UserKey = "user"
DomainKey = "domain"
ChannelKey = "channel"
DefPermission = "read_permission"
DefTotal = uint64(100)
DefOffset = 0
DefOrder = "updated_at"
DefDir = "asc"
DefLimit = 10
DefLevel = 0
DefStartLevel = 1
DefEndLevel = 0
DefStatus = "enabled"
DefClientStatus = clients.Enabled
DefUserStatus = users.Enabled
DefGroupStatus = groups.Enabled
DefListPerms = false
SharedVisibility = "shared"
MyVisibility = "mine"
AllVisibility = "all"
OffsetKey = "offset"
DirKey = "dir"
OrderKey = "order"
LimitKey = "limit"
OnlyTotal = "only_total"
NameOrder = "name"
IDOrder = "id"
AscDir = "asc"
DescDir = "desc"
UpdatedAtOrder = "updated_at"
CreatedAtOrder = "created_at"
MetadataKey = "metadata"
NameKey = "name"
TagKey = "tag"
StatusKey = "status"
ClientKey = "client"
ChannelKey = "channel"
ConnTypeKey = "connection_type"
GroupKey = "group"
DomainKey = "domain"
StartLevelKey = "start_level"
EndLevelKey = "end_level"
TreeKey = "tree"
ParentKey = "parent_id"
LevelKey = "level"
RootGroupKey = "root_group"
TokenKey = "token"
SubjectKey = "subject"
ObjectKey = "object"
RolesKey = "roles"
ActionKey = "action"
ActionsKey = "actions"
RoleIDKey = "role_id"
RoleNameKey = "role_name"
AccessProviderIDKey = "access_provider_id"
AccessTypeKey = "access_type"
UsernameKey = "username"
UserKey = "user"
EmailKey = "email"
FirstNameKey = "first_name"
LastNameKey = "last_name"
DefTotal = uint64(100)
DefOffset = 0
DefOrder = "updated_at"
DefDir = "desc"
DefLimit = 10
DefLevel = 0
DefStartLevel = 1
DefEndLevel = 0
DefStatus = "enabled"
DefClientStatus = clients.Enabled
DefUserStatus = users.Enabled
DefGroupStatus = groups.Enabled
// ContentType represents JSON content type.
ContentType = "application/json"
@@ -83,10 +91,13 @@ const (
MaxLimitSize = 100
MaxNameSize = 1024
MaxIDSize = 36
NameOrder = "name"
IDOrder = "id"
AscDir = "asc"
DescDir = "desc"
)
var (
nameRegExp = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]{34}[a-z0-9]$`)
routeRegExp = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]{0,35}$`)
userNameRegExp = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_-]{0,31}$`)
errUnreadableName = errors.New("name containing double underscores or double dashes not allowed")
)
// ValidateUUID validates UUID format.
@@ -99,8 +110,54 @@ func ValidateUUID(extID string) (err error) {
return nil
}
func ValidateEmail(email string) (err error) {
if _, err := mail.ParseAddress(email); err != nil {
return apiutil.ErrInvalidEmail
}
return nil
}
// ValidateName validates name format.
func ValidateName(id string) error {
if !nameRegExp.MatchString(id) {
return apiutil.ErrInvalidNameFormat
}
// Names containing double underscores or double dashes are invalid due to similarity concerns.
if strings.Contains(id, "__") || strings.Contains(id, "--") {
return errors.Wrap(apiutil.ErrInvalidNameFormat, errUnreadableName)
}
return nil
}
// ValidateRoute validates route format.
func ValidateRoute(route string) error {
if !routeRegExp.MatchString(route) {
return apiutil.ErrInvalidRouteFormat
}
if strings.Contains(route, "__") || strings.Contains(route, "--") {
return errors.Wrap(apiutil.ErrInvalidRouteFormat, errUnreadableName)
}
return nil
}
// ValidateUserName validates user name format.
func ValidateUserName(name string) error {
if !userNameRegExp.MatchString(name) {
return apiutil.ErrInvalidUsername
}
if strings.Contains(name, "__") || strings.Contains(name, "--") {
return errors.Wrap(apiutil.ErrInvalidUsername, errUnreadableName)
}
return nil
}
// EncodeResponse encodes successful response.
func EncodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
func EncodeResponse(_ context.Context, w http.ResponseWriter, response any) error {
if ar, ok := response.(supermq.Response); ok {
for k, v := range ar.Headers() {
w.Header().Set(k, v)
@@ -118,23 +175,43 @@ func EncodeResponse(_ context.Context, w http.ResponseWriter, response interface
// EncodeError encodes an error response.
func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
w.Header().Set("Content-Type", ContentType)
if sdkErr, ok := err.(errors.SDKError); ok {
w.WriteHeader(sdkErr.StatusCode())
if err := json.NewEncoder(w).Encode(sdkErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
}
var wrapper error
if errors.Contains(err, apiutil.ErrValidation) {
wrapper, err = errors.Unwrap(err)
}
w.Header().Set("Content-Type", ContentType)
switch {
case errors.Contains(err, errors.ErrTryAgain):
w.WriteHeader(http.StatusUnprocessableEntity)
case errors.Contains(err, errors.ErrEmailAlreadyExists),
errors.Contains(err, errors.ErrUsernameNotAvailable),
errors.Contains(err, errors.ErrRouteNotAvailable),
errors.Contains(err, errors.ErrChannelRouteNotAvailable),
errors.Contains(err, errors.ErrDomainRouteNotAvailable),
errors.Contains(err, svcerr.ErrExternalAuthProviderCouldNotChangePassword),
errors.Contains(err, svcerr.ErrExternalAuthProviderCouldNotResetPassword),
errors.Contains(err, svcerr.ErrExternalAuthProviderCouldNotUpdate):
w.WriteHeader(http.StatusBadRequest)
case errors.Contains(err, svcerr.ErrAuthorization),
errors.Contains(err, svcerr.ErrDomainAuthorization),
errors.Contains(err, bootstrap.ErrExternalKey),
errors.Contains(err, bootstrap.ErrExternalKeySecure):
errors.Contains(err, svcerr.ErrUnauthorizedPAT),
errors.Contains(err, svcerr.ErrSuperAdminAction):
err = unwrap(err)
w.WriteHeader(http.StatusForbidden)
case errors.Contains(err, svcerr.ErrAuthentication),
errors.Contains(err, apiutil.ErrBearerToken),
errors.Contains(err, svcerr.ErrLogin):
errors.Contains(err, svcerr.ErrLogin),
errors.Contains(err, apiutil.ErrUnsupportedTokenType):
err = unwrap(err)
w.WriteHeader(http.StatusUnauthorized)
case errors.Contains(err, svcerr.ErrMalformedEntity),
@@ -142,8 +219,8 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
errors.Contains(err, apiutil.ErrMissingSecret),
errors.Contains(err, errors.ErrMalformedEntity),
errors.Contains(err, apiutil.ErrMissingID),
errors.Contains(err, apiutil.ErrInvalidVerification),
errors.Contains(err, apiutil.ErrMissingName),
errors.Contains(err, apiutil.ErrMissingAlias),
errors.Contains(err, apiutil.ErrMissingEmail),
errors.Contains(err, apiutil.ErrInvalidEmail),
errors.Contains(err, apiutil.ErrMissingHost),
@@ -167,11 +244,9 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
errors.Contains(err, apiutil.ErrInvitationState),
errors.Contains(err, apiutil.ErrInvalidAPIKey),
errors.Contains(err, svcerr.ErrViewEntity),
errors.Contains(err, apiutil.ErrBootstrapState),
errors.Contains(err, apiutil.ErrMissingCertData),
errors.Contains(err, apiutil.ErrInvalidContact),
errors.Contains(err, apiutil.ErrInvalidTopic),
errors.Contains(err, bootstrap.ErrAddBootstrap),
errors.Contains(err, apiutil.ErrInvalidCertData),
errors.Contains(err, apiutil.ErrEmptyMessage),
errors.Contains(err, apiutil.ErrInvalidLevel),
@@ -183,8 +258,10 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
errors.Contains(err, apiutil.ErrEmptySearchQuery),
errors.Contains(err, apiutil.ErrLenSearchQuery),
errors.Contains(err, apiutil.ErrMissingDomainID),
errors.Contains(err, certs.ErrFailedReadFromPKI),
errors.Contains(err, apiutil.ErrMissingUserID),
errors.Contains(err, apiutil.ErrMissingPATID),
errors.Contains(err, apiutil.ErrMissingUsername),
errors.Contains(err, apiutil.ErrMissingUsernameEmail),
errors.Contains(err, apiutil.ErrMissingFirstName),
errors.Contains(err, apiutil.ErrMissingLastName),
errors.Contains(err, apiutil.ErrInvalidUsername),
@@ -195,8 +272,14 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
errors.Contains(err, apiutil.ErrMissingParentGroupID),
errors.Contains(err, apiutil.ErrMissingConnectionType),
errors.Contains(err, apiutil.ErrMissingRoleName),
errors.Contains(err, apiutil.ErrMissingRoleID),
errors.Contains(err, apiutil.ErrMissingPolicyEntityType),
errors.Contains(err, apiutil.ErrMissingRoleMembers):
errors.Contains(err, apiutil.ErrMissingRoleMembers),
errors.Contains(err, apiutil.ErrMissingDescription),
errors.Contains(err, apiutil.ErrMissingEntityID),
errors.Contains(err, apiutil.ErrInvalidRouteFormat),
errors.Contains(err, svcerr.ErrRetainOneMember),
errors.Contains(err, apiutil.ErrMissingRoute):
err = unwrap(err)
w.WriteHeader(http.StatusBadRequest)
@@ -209,8 +292,7 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
err = unwrap(err)
w.WriteHeader(http.StatusUnprocessableEntity)
case errors.Contains(err, svcerr.ErrNotFound),
errors.Contains(err, bootstrap.ErrBootstrap):
case errors.Contains(err, svcerr.ErrNotFound):
err = unwrap(err)
w.WriteHeader(http.StatusNotFound)
@@ -1,7 +1,7 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api_test
package http_test
import (
"context"
@@ -11,9 +11,9 @@ import (
"time"
"github.com/absmach/supermq"
"github.com/absmach/supermq/internal/api"
api "github.com/absmach/supermq/api/http"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/internal/testsutil"
"github.com/absmach/supermq/pkg/apiutil"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/stretchr/testify/assert"
@@ -115,7 +115,7 @@ func TestEncodeResponse(t *testing.T) {
cases := []struct {
desc string
resp interface{}
resp any
header http.Header
code int
body []byte
+6
View File
@@ -0,0 +1,6 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package api contains commonly used constants and functions
// for the HTTP API.
package http
+27
View File
@@ -0,0 +1,27 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package http
import (
"context"
"net/http"
"github.com/absmach/supermq"
"github.com/go-chi/chi/v5/middleware"
)
func RequestIDMiddleware(idp supermq.IDProvider) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestID, err := idp.ID()
if err != nil {
EncodeError(r.Context(), err, w)
return
}
ctx := context.WithValue(r.Context(), middleware.RequestIDKey, requestID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
@@ -1,7 +1,7 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package apiutil
package util
import "github.com/absmach/supermq/pkg/errors"
@@ -21,6 +21,9 @@ var (
// ErrMissingID indicates missing entity ID.
ErrMissingID = errors.New("missing entity id")
// ErrMissingEntityID indicates missing entity ID.
ErrMissingEntityID = errors.New("missing entity id")
// ErrMissingClientID indicates missing client ID.
ErrMissingClientID = errors.New("missing cient id")
@@ -78,9 +81,12 @@ var (
// ErrEmptyList indicates that entity data is empty.
ErrEmptyList = errors.New("empty list provided")
// ErrMissingRoleName indicates that role name are empty.
// ErrMissingRoleName indicates that role name is empty.
ErrMissingRoleName = errors.New("empty role name")
// ErrMissingRoleID indicates that role id is empty.
ErrMissingRoleID = errors.New("empty role id")
// ErrMissingRoleOperations indicates that role operations are empty.
ErrMissingRoleOperations = errors.New("empty role operations")
@@ -138,6 +144,9 @@ var (
// ErrInvalidComparator indicates an invalid comparator.
ErrInvalidComparator = errors.New("invalid comparator")
// ErrMissingMemberIDs indicates missing member ids.
ErrMissingMemberIDs = errors.New("missing member ids")
// ErrMissingMemberType indicates missing group member type.
ErrMissingMemberType = errors.New("missing group member type")
@@ -153,9 +162,6 @@ var (
// ErrInvalidAPIKey indicates an invalid API key type.
ErrInvalidAPIKey = errors.New("invalid api key type")
// ErrBootstrapState indicates an invalid bootstrap state.
ErrBootstrapState = errors.New("invalid bootstrap state")
// ErrInvitationState indicates an invalid invitation state.
ErrInvitationState = errors.New("invalid invitation state")
@@ -171,8 +177,8 @@ var (
// ErrMissingName indicates missing identity name.
ErrMissingName = errors.New("missing identity name")
// ErrMissingName indicates missing alias.
ErrMissingAlias = errors.New("missing alias")
// ErrMissingRoute indicates missing route.
ErrMissingRoute = errors.New("missing route")
// ErrInvalidLevel indicates an invalid group level.
ErrInvalidLevel = errors.New("invalid group level (should be between 0 and 5)")
@@ -228,7 +234,7 @@ var (
// ErrMissingUsername indicates missing user name.
ErrMissingUsername = errors.New("missing username")
// ErrInvalidUsername indicates missing user name.
// ErrInvalidUsername indicates invalid user name.
ErrInvalidUsername = errors.New("invalid username")
// ErrMissingFirstName indicates missing first name.
@@ -241,4 +247,31 @@ var (
ErrInvalidProfilePictureURL = errors.New("invalid profile picture url")
ErrMultipleEntitiesFilter = errors.New("multiple entities are provided in filter are not supported")
// ErrMissingDescription indicates missing description.
ErrMissingDescription = errors.New("missing description")
// ErrUnsupportedTokenType indicates that this type of token is not supported.
ErrUnsupportedTokenType = errors.New("unsupported content token type")
// ErrMissingUserID indicates missing user ID.
ErrMissingUserID = errors.New("missing user id")
// ErrMissingPATID indicates missing pat ID.
ErrMissingPATID = errors.New("missing pat id")
// ErrInvalidNameFormat indicates invalid name format.
ErrInvalidNameFormat = errors.New("invalid name format")
// ErrInvalidRouteFormat indicates invalid route format.
ErrInvalidRouteFormat = errors.New("invalid route format")
// ErrMissingUsernameEmail indicates missing user name / email.
ErrMissingUsernameEmail = errors.New("missing username / email")
// ErrInvalidVerification indicates invalid email verification.
ErrInvalidVerification = errors.New("invalid verification")
// ErrEmailNotVerified indicates invalid email not verified.
ErrEmailNotVerified = errors.New("email not verified")
)
@@ -1,7 +1,7 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package apiutil
package util
// ErrorRes represents the HTTP error response body.
type ErrorRes struct {
@@ -1,7 +1,7 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package apiutil
package util
import (
"net/http"
@@ -1,13 +1,13 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package apiutil_test
package util_test
import (
"net/http"
"testing"
"github.com/absmach/supermq/pkg/apiutil"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/stretchr/testify/assert"
)
@@ -1,7 +1,7 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package apiutil
package util
import (
"context"
@@ -39,7 +39,7 @@ func ReadStringQuery(r *http.Request, key, def string) (string, error) {
}
// ReadMetadataQuery reads the value of json http query parameters for a given key.
func ReadMetadataQuery(r *http.Request, key string, def map[string]interface{}) (map[string]interface{}, error) {
func ReadMetadataQuery(r *http.Request, key string, def map[string]any) (map[string]any, error) {
vals := r.URL.Query()[key]
if len(vals) > 1 {
return nil, ErrInvalidQueryParams
@@ -49,7 +49,7 @@ func ReadMetadataQuery(r *http.Request, key string, def map[string]interface{})
return def, nil
}
m := make(map[string]interface{})
m := make(map[string]any)
err := json.Unmarshal([]byte(vals[0]), &m)
if err != nil {
return nil, errors.Wrap(ErrInvalidQueryParams, err)
@@ -1,7 +1,7 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package apiutil_test
package util_test
import (
"context"
@@ -11,8 +11,8 @@ import (
"net/url"
"testing"
apiutil "github.com/absmach/supermq/api/http/util"
smqlog "github.com/absmach/supermq/logger"
"github.com/absmach/supermq/pkg/apiutil"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/stretchr/testify/assert"
@@ -67,14 +67,14 @@ func TestReadMetadataQuery(t *testing.T) {
desc string
url string
key string
ret map[string]interface{}
ret map[string]any
err error
}{
{
desc: "valid metadata query",
url: "http://localhost:8080/?key={\"test\":\"test\"}",
key: "key",
ret: map[string]interface{}{"test": "test"},
ret: map[string]any{"test": "test"},
err: nil,
},
{
@@ -177,7 +177,7 @@ func TestReadNumQuery(t *testing.T) {
url string
key string
numType string
ret interface{}
ret any
err error
}{
{
@@ -316,7 +316,7 @@ func TestReadNumQuery(t *testing.T) {
assert.NoError(t, err)
r := &http.Request{URL: parsedURL}
var ret interface{}
var ret any
switch c.numType {
case "int64":
ret, err = apiutil.ReadNumQuery[int64](r, c.key, 0)
-5
View File
@@ -1,5 +0,0 @@
# SuperMQ OpenAPI Specification
This folder contains an OpenAPI specifications for SuperMQ API.
View specification in Swagger UI at [docs.api.magistrala.abstractmachines.fr](https://docs.api.supermq.abstractmachines.fr)
-285
View File
@@ -1,285 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.3
info:
title: SuperMQ 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 SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
servers:
- url: http://localhost:9001
- url: https://localhost:9001
tags:
- name: Keys
description: Everything about your Keys.
externalDocs:
description: Find out more about keys
url: https://docs.supermq.abstractmachines.fr/
- name: Health
description: Service health check endpoint.
externalDocs:
description: Find out more about health check
url: https://docs.supermq.abstractmachines.fr/
paths:
/keys:
post:
operationId: issueKey
tags:
- Keys
summary: Issue API key
description: |
Generates a new API key. Thew new API key will
be uniquely identified by its ID.
requestBody:
$ref: "#/components/requestBodies/KeyRequest"
responses:
"201":
description: Issued new key.
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"409":
description: Failed due to using already existing ID.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/keys/{keyID}:
get:
operationId: getKey
summary: Gets API key details.
description: |
Gets API key details for the given key.
tags:
- Keys
parameters:
- $ref: "#/components/parameters/ApiKeyId"
responses:
"200":
$ref: "#/components/responses/KeyRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"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"
/health:
get:
summary: Retrieves service health check info.
tags:
- Health
security: []
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
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:
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.
KeyRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Key"
links:
revoke:
operationId: revokeKey
parameters:
keyID: $response.body#/id
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
-690
View File
@@ -1,690 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: SuperMQ Bootstrap service
description: |
HTTP API for managing platform clients configuration.
Some useful links:
- [The SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
servers:
- url: http://localhost:9013
- url: https://localhost:9013
tags:
- name: configs
description: Everything about your Configs
externalDocs:
description: Find out more about Configs
url: https://docs.supermq.abstractmachines.fr/
paths:
/{domainID}/clients/configs:
post:
operationId: createConfig
summary: Adds new config
description: |
Adds new config to the list of config owned by user identified using
the provided access token.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/ConfigCreateReq"
responses:
"201":
$ref: "#/components/responses/ConfigCreateRes"
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
"503":
description: Failed to receive response from the clients service.
get:
operationId: getConfigs
summary: Retrieves managed configs
description: |
Retrieves a list of managed configs. Due to performance concerns, data
is retrieved in subsets. The API configs must ensure that the entire
dataset is consumed either by making subsequent requests, or by
increasing the subset size of the initial request.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/State"
- $ref: "#/components/parameters/Name"
responses:
"200":
$ref: "#/components/responses/ConfigListRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/configs/{configId}:
get:
operationId: getConfig
summary: Retrieves config info (with channels).
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
responses:
"200":
$ref: "#/components/responses/ConfigRes"
"400":
description: Missing or invalid config.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Config does not exist.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
put:
operationId: updateConfig
summary: Updates config info
description: |
Update is performed by replacing the current resource data with values
provided in a request payload. Note that the owner, ID, external ID,
external key, SuperMQ Client ID and key cannot be changed.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigUpdateReq"
responses:
"200":
description: Config updated.
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Config does not exist.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: removeConfig
summary: Removes a Config
description: |
Removes a Config. In case of successful removal the service will ensure
that the removed config is disconnected from all of the SuperMQ channels.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
responses:
"204":
description: Config removed.
"400":
description: Failed due to malformed config ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/configs/certs/{configId}:
patch:
operationId: updateConfigCerts
summary: Updates certs
description: |
Update is performed by replacing the current certificate data with values
provided in a request payload.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigCertUpdateReq"
responses:
"200":
description: Config updated.
$ref: "#/components/responses/ConfigUpdateCertsRes"
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Config does not exist.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/configs/connections/{configId}:
put:
operationId: updateConfigConnections
summary: Updates channels the client is connected to
description: |
Update connections performs update of the channel list corresponding
Client is connected to.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigConnUpdateReq"
responses:
"200":
description: Config updated.
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Config does not exist.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/clients/bootstrap/{externalId}:
get:
operationId: getBootstrapConfig
summary: Retrieves configuration.
description: |
Retrieves a configuration with given external ID and external key.
tags:
- configs
security:
- bootstrapAuth: []
parameters:
- $ref: "#/components/parameters/ExternalId"
responses:
"200":
$ref: "#/components/responses/BootstrapConfigRes"
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid external key provided.
"404":
description: Failed to retrieve corresponding config.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/clients/bootstrap/secure/{externalId}:
get:
operationId: getSecureBootstrapConfig
summary: Retrieves configuration.
description: |
Retrieves a configuration with given external ID and encrypted external key.
tags:
- configs
security:
- bootstrapEncAuth: []
parameters:
- $ref: "#/components/parameters/ExternalId"
responses:
"200":
$ref: "#/components/responses/BootstrapConfigRes"
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"404":
description: |
Failed to retrieve corresponding config.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/state/{configId}:
put:
operationId: updateConfigState
summary: Updates Config state.
description: |
Updating state represents enabling/disabling Config, i.e. connecting
and disconnecting corresponding SuperMQ Client to the list of Channels.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigStateUpdateReq"
responses:
"204":
description: Config removed.
"400":
description: Failed due to malformed config's ID.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
State:
type: integer
enum: [0, 1]
Config:
type: object
properties:
client_id:
type: string
format: uuid
description: Corresponding SuperMQ Client ID.
magistrala_secret:
type: string
format: uuid
description: Corresponding SuperMQ Client key.
channels:
type: array
minItems: 0
items:
type: object
properties:
id:
type: string
format: uuid
description: Channel unique identifier.
name:
type: string
description: Name of the Channel.
metadata:
type: object
description: Custom metadata related to the Channel.
external_id:
type: string
description: External ID (MAC address or some unique identifier).
external_key:
type: string
description: External key.
content:
type: string
description: Free-form custom configuration.
state:
$ref: "#/components/schemas/State"
client_cert:
type: string
description: Client certificate.
ca_cert:
type: string
description: Issuing CA certificate.
required:
- external_id
- external_key
ConfigList:
type: object
properties:
total:
type: integer
description: Total number of results.
minimum: 0
offset:
type: integer
description: Number of items to skip during retrieval.
minimum: 0
default: 0
limit:
type: integer
description: Size of the subset to retrieve.
maximum: 100
default: 10
configs:
type: array
minItems: 0
uniqueItems: true
items:
$ref: "#/components/schemas/Config"
required:
- configs
BootstrapConfig:
type: object
properties:
client_id:
type: string
format: uuid
description: Corresponding SuperMQ Client ID.
client_key:
type: string
format: uuid
description: Corresponding SuperMQ Client key.
channels:
type: array
minItems: 0
items:
type: string
content:
type: string
description: Free-form custom configuration.
client_cert:
type: string
description: Client certificate.
required:
- client_id
- client_key
- channels
- content
ConfigUpdateCerts:
type: object
properties:
client_id:
type: string
format: uuid
description: Corresponding SuperMQ Client ID.
client_cert:
type: string
description: Client certificate.
client_key:
type: string
description: Key for the client_cert.
ca_cert:
type: string
description: Issuing CA certificate.
required:
- client_id
- client_key
- channels
- content
parameters:
ConfigId:
name: configId
description: Unique Config identifier. It's the ID of the corresponding Client.
in: path
schema:
type: string
format: uuid
required: true
ExternalId:
name: externalId
description: Unique Config identifier provided by external entity.
in: path
schema:
type: string
required: true
Limit:
name: limit
description: Size of the subset to retrieve.
in: query
schema:
type: integer
default: 10
maximum: 100
minimum: 1
required: false
Offset:
name: offset
description: Number of items to skip during retrieval.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
State:
name: state
description: A state of items
in: query
schema:
$ref: "#/components/schemas/State"
required: false
Name:
name: name
description: Name of the config. Search by name is partial-match and case-insensitive.
in: query
schema:
type: string
required: false
requestBodies:
ConfigCreateReq:
description: JSON-formatted document describing the new config.
required: true
content:
application/json:
schema:
type: object
properties:
external_id:
type: string
description: External ID (MAC address or some unique identifier).
external_key:
type: string
description: External key.
client_id:
type: string
format: uuid
description: ID of the corresponding SuperMQ Client.
channels:
type: array
minItems: 0
items:
type: string
format: uuid
content:
type: string
name:
type: string
client_cert:
type: string
description: Client Certificate.
client_key:
type: string
description: Client Private Key.
ca_cert:
type: string
required:
- external_id
- external_key
ConfigUpdateReq:
description: JSON-formatted document describing the updated client.
content:
application/json:
schema:
type: object
properties:
content:
type: string
name:
type: string
required:
- content
- name
ConfigCertUpdateReq:
description: JSON-formatted document describing the updated client.
content:
application/json:
schema:
type: object
properties:
client_cert:
type: string
client_key:
type: string
ca_cert:
type: string
ConfigConnUpdateReq:
description: Array if IDs the client is be connected to.
content:
application/json:
schema:
type: object
properties:
channels:
type: array
minItems: 0
items:
type: string
format: uuid
ConfigStateUpdateReq:
description: Update the state of the Config.
content:
application/json:
schema:
type: object
properties:
state:
$ref: "#/components/schemas/State"
responses:
ConfigCreateRes:
description: Config registered.
headers:
Location:
content:
text/plain:
schema:
type: string
description: Created configuration's relative URL (i.e. /clients/configs/{configId}).
ConfigListRes:
description: Data retrieved. Configs from this list don't contain channels.
content:
application/json:
schema:
$ref: "#/components/schemas/ConfigList"
ConfigRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Config"
links:
update:
operationId: updateConfig
parameters:
configId: $response.body#/id
updateCerts:
operationId: updateConfigCerts
parameters:
configId: $response.body#/id
updateConnections:
operationId: updateConfigConnections
parameters:
configId: $response.body#/id
updateState:
operationId: updateConfigState
parameters:
configId: $response.body#/id
delete:
operationId: removeConfig
parameters:
configId: $response.body#/id
BootstrapConfigRes:
description: |
Data retrieved. If secure, a response is encrypted using
the secret key, so the response is in the binary form.
content:
application/json:
schema:
$ref: "#/components/schemas/BootstrapConfig"
ServiceError:
description: Unexpected server-side error occurred.
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yml"
ConfigUpdateCertsRes:
description: Data retrieved. Config certs updated.
content:
application/json:
schema:
$ref: "#/components/schemas/ConfigUpdateCerts"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
bootstrapAuth:
type: http
scheme: bearer
bearerFormat: string
description: |
* Clients access: "Authorization: Client <external_key>"
bootstrapEncAuth:
type: http
scheme: bearer
bearerFormat: aes-sha256-uuid
description: |
* 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.
security:
- bearerAuth: []
-316
View File
@@ -1,316 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: SuperMQ Certs service
description: |
HTTP API for Certs service
Some useful links:
- [The SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
servers:
- url: http://localhost:9019
- url: https://localhost:9019
tags:
- name: certs
description: Everything about your Certs
externalDocs:
description: Find out more about certs
url: https://docs.supermq.abstractmachines.fr/
paths:
/{domainID}/certs:
post:
operationId: createCert
summary: Creates a certificate for client
description: Creates a certificate for client
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/{clientID}:
get:
operationId: getSerials
summary: Retrieves certificates' serial IDs
description: |
Retrieves a list of certificates' serial IDs for a given client ID.
tags:
- certs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/ClientID"
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:
ClientID:
name: clientID
description: Client 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:
client_id:
type: string
format: uuid
description: Corresponding SuperMQ Client ID.
client_cert:
type: string
description: Client Certificate.
client_key:
type: string
description: Key for the client_cert.
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 client
provide a client id, data identifying particular client 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:
- client_id
- ttl
properties:
client_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:
clientID: $response.body#/client_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/health_info.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
-537
View File
@@ -1,537 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.3
info:
title: SuperMQ 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 SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
servers:
- url: http://localhost:9020
- url: https://localhost:9020
tags:
- name: Invitations
description: Everything about your Invitations
externalDocs:
description: Find out more about Invitations
url: https://docs.supermq.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: []
-292
View File
@@ -1,292 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: SuperMQ Notifiers service
description: |
HTTP API for Notifiers service.
Some useful links:
- [The SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
servers:
- url: http://localhost:9014
- url: https://localhost:9014
- url: http://localhost:9015
- url: https://localhost:9015
tags:
- name: notifiers
description: Everything about your Notifiers
externalDocs:
description: Find out more about notifiers
url: https://docs.supermq.abstractmachines.fr/
paths:
/subscriptions:
post:
operationId: createSubscription
summary: Create subscription
description: Creates a new subscription give a topic and contact.
tags:
- notifiers
requestBody:
$ref: "#/components/requestBodies/Create"
responses:
"201":
$ref: "#/components/responses/Create"
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"409":
description: Failed due to using an existing topic and contact.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listSubscriptions
summary: List subscriptions
description: List subscriptions given list parameters.
tags:
- notifiers
parameters:
- $ref: "#/components/parameters/Topic"
- $ref: "#/components/parameters/Contact"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Limit"
responses:
"200":
$ref: "#/components/responses/Page"
"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"
/subscriptions/{id}:
get:
operationId: viewSubscription
summary: Get subscription with the provided id
description: Retrieves a subscription with the provided id.
tags:
- notifiers
parameters:
- $ref: "#/components/parameters/Id"
responses:
"200":
$ref: "#/components/responses/View"
"400":
description: Failed due to malformed ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: removeSubscription
summary: Delete subscription with the provided id
description: Removes a subscription with the provided id.
tags:
- notifiers
parameters:
- $ref: "#/components/parameters/Id"
responses:
"204":
description: Subscription removed
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
Subscription:
type: object
properties:
id:
type: string
format: ulid
example: 01EWDVKBQSG80B6PQRS9PAAY35
description: ULID id of the subscription.
owner_id:
type: string
format: uuid
example: 18167738-f7a8-4e96-a123-58c3cd14de3a
description: An id of the owner who created subscription.
topic:
type: string
example: topic.subtopic
description: Topic to which the user subscribes.
contact:
type: string
example: user@example.com
description: The contact of the user to which the notification will be sent.
CreateSubscription:
type: object
properties:
topic:
type: string
example: topic.subtopic
description: Topic to which the user subscribes.
contact:
type: string
example: user@example.com
description: The contact of the user to which the notification will be sent.
Page:
type: object
properties:
subscriptions:
type: array
minItems: 0
uniqueItems: true
items:
$ref: "#/components/schemas/Subscription"
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.
parameters:
Id:
name: id
description: Unique identifier.
in: path
schema:
type: string
format: ulid
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
Topic:
name: topic
description: Topic name.
in: query
schema:
type: string
required: false
Contact:
name: contact
description: Subscription contact.
in: query
schema:
type: string
required: false
requestBodies:
Create:
description: JSON-formatted document describing the new subscription to be created
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateSubscription"
responses:
Create:
description: Created a new subscription.
headers:
Location:
content:
text/plain:
schema:
type: string
description: Created subscription relative URL
example: /subscriptions/{id}
View:
description: View subscription.
content:
application/json:
schema:
$ref: "#/components/schemas/Subscription"
links:
delete:
operationId: removeSubscription
parameters:
id: $response.body#/id
Page:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Page"
ServiceError:
description: Unexpected server-side error occurred.
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
-133
View File
@@ -1,133 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: SuperMQ Provision service
description: |
HTTP API for Provision service
Some useful links:
- [The SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstracmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
servers:
- url: http://localhost:9016
- url: https://localhost:9016
tags:
- name: provision
description: Everything about your Provision
externalDocs:
description: Find out more about provision
url: https://docs.supermq.abstractmachines.fr/
paths:
/{domainID}/mapping:
post:
summary: Adds new device to proxy
description: Adds new device to proxy
tags:
- provision
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/ProvisionReq"
responses:
"201":
description: Created
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
summary: Gets current mapping.
description: Gets current mapping. This can be used in UI
so that when bootstrap config is created from UI matches
configuration created with provision service.
tags:
- provision
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
responses:
"200":
$ref: "#/components/responses/ProvisionRes"
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
requestBodies:
ProvisionReq:
description: MAC address of device or other identifier
content:
application/json:
schema:
type: object
required:
- external_id
- external_key
properties:
external_id:
type: string
external_key:
type: string
name:
type: string
responses:
ServiceError:
description: Unexpected server-side error occurred.
ProvisionRes:
description: Current mapping JSON representation.
content:
application/json:
schema:
type: object
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <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: SuperMQ reader service
description: |
HTTP API for reading messages.
Some useful links:
- [The SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
servers:
- url: http://localhost:9003
- url: https://localhost:9003
- url: http://localhost:9005
- url: https://localhost:9005
- url: http://localhost:9007
- url: https://localhost:9007
- url: http://localhost:9009
- url: https://localhost:9009
- url: http://localhost:9011
- url: https://localhost:9011
tags:
- name: readers
description: Everything about your Readers
externalDocs:
description: Find out more about readers
url: https://docs.supermq.abstractmachines.fr/
paths:
/channels/{chanId}/messages:
get:
operationId: getMessages
summary: Retrieves messages sent to single channel
description: |
Retrieves a list of messages sent to specific channel. Due to
performance concerns, data is retrieved in subsets. The API readers must
ensure that the entire dataset is consumed either by making subsequent
requests, or by increasing the subset size of the initial request.
tags:
- readers
parameters:
- $ref: "#/components/parameters/ChanId"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Publisher"
- $ref: "#/components/parameters/Name"
- $ref: "#/components/parameters/Value"
- $ref: "#/components/parameters/BoolValue"
- $ref: "#/components/parameters/StringValue"
- $ref: "#/components/parameters/DataValue"
- $ref: "#/components/parameters/From"
- $ref: "#/components/parameters/To"
- $ref: "#/components/parameters/Aggregation"
- $ref: "#/components/parameters/Interval"
responses:
"200":
$ref: "#/components/responses/MessagesPageRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
operationId: health
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
MessagesPage:
type: object
properties:
total:
type: number
description: Total number of items that are present on the system.
offset:
type: number
description: Number of items that were skipped during retrieval.
limit:
type: number
description: Size of the subset that was retrieved.
messages:
type: array
minItems: 0
uniqueItems: true
items:
type: object
properties:
channel:
type: integer
description: Unique channel id.
publisher:
type: integer
description: Unique publisher id.
protocol:
type: string
description: Protocol name.
name:
type: string
description: Measured parameter name.
unit:
type: string
description: Value unit.
value:
type: number
description: Measured value in number.
stringValue:
type: string
description: Measured value in string format.
boolValue:
type: boolean
description: Measured value in boolean format.
dataValue:
type: string
description: Measured value in binary format.
valueSum:
type: number
description: Sum value.
time:
type: number
description: Time of measurement.
updateTime:
type: number
description: Time of updating measurement.
parameters:
DomainID:
name: domainID
description: Unique domain identifier.
in: path
schema:
type: string
format: uuid
required: true
ChanId:
name: chanId
description: Unique channel identifier.
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
Publisher:
name: Publisher
description: Unique client identifier.
in: query
schema:
type: string
format: uuid
required: false
Name:
name: name
description: SenML message name.
in: query
schema:
type: string
required: false
Value:
name: v
description: SenML message value.
in: query
schema:
type: string
required: false
BoolValue:
name: vb
description: SenML message bool value.
in: query
schema:
type: boolean
required: false
StringValue:
name: vs
description: SenML message string value.
in: query
schema:
type: string
required: false
DataValue:
name: vd
description: SenML message data value.
in: query
schema:
type: string
required: false
Comparator:
name: comparator
description: Value comparison operator.
in: query
schema:
type: string
default: eq
enum:
- eq
- lt
- le
- gt
- ge
required: false
From:
name: from
description: SenML message time in nanoseconds (integer part represents seconds).
in: query
schema:
type: number
example: 1709218556069
required: false
To:
name: to
description: SenML message time in nanoseconds (integer part represents seconds).
in: query
schema:
type: number
example: 1709218757503
required: false
Aggregation:
name: aggregation
description: Aggregation function.
in: query
schema:
type: string
enum:
- MAX
- AVG
- MIN
- SUM
- COUNT
- max
- min
- sum
- avg
- count
example: MAX
required: false
Interval:
name: interval
description: Aggregation interval.
in: query
schema:
type: string
example: 10s
required: false
responses:
MessagesPageRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/MessagesPage"
ServiceError:
description: Unexpected server-side error occurred.
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
clientAuth:
type: http
scheme: bearer
bearerFormat: uuid
description: |
* Clients access: "Authorization: Client <client_key>"
security:
- bearerAuth: []
- clientAuth: []
@@ -2,10 +2,10 @@
# SPDX-License-Identifier: Apache-2.0
asyncapi: '2.6.0'
id: 'https://github.com/absmach/supermq/blob/main/api/asyncapi/mqtt.yml'
id: 'https://github.com/absmach/supermq/blob/main/api/asyncapi/mqtt.yaml'
info:
title: SuperMQ MQTT Adapter
version: '1.0.0'
version: '0.18.0'
contact:
name: SuperMQ Team
url: 'https://github.com/absmach/supermq'
@@ -37,10 +37,14 @@ servers:
- user-password: []
channels:
channels/{channelID}/messages/{subtopic}:
/m/{domainPrefix}/c/{channelPrefix}/{subtopic}:
parameters:
channelID:
$ref: '#/components/parameters/channelID'
domainPrefix:
$ref: '#/components/parameters/domainPrefix'
in: path
required: true
channelPrefix:
$ref: '#/components/parameters/channelPrefix'
in: path
required: true
subtopic:
@@ -87,11 +91,14 @@ components:
```
parameters:
channelID:
description: Channel ID connected to the Client ID defined in the username.
domainPrefix:
description: ID or route of the domain associated with the channel and client.
schema:
type: string
channelPrefix:
description: ID or route of the channel connected to the Client ID defined in the username.
schema:
type: string
format: uuid
subtopic:
description: Arbitrary message subtopic.
schema:
@@ -2,11 +2,11 @@
# SPDX-License-Identifier: Apache-2.0
asyncapi: 2.6.0
id: 'https://github.com/absmach/supermq/blob/main/api/asyncapi/websocket.yml'
id: 'https://github.com/absmach/supermq/blob/main/api/asyncapi/websocket.yaml'
info:
title: SuperMQ WebSocket adapter
description: WebSocket adapter provides a WebSocket API for sending messages through communication channels. WebSocket adapter uses [mProxy](https://github.com/absmach/mproxy) for proxying traffic between client and MQTT broker.
version: '1.0.0'
version: '0.18.0'
contact:
name: SuperMQ Team
url: 'https://github.com/absmach/supermq'
@@ -32,10 +32,14 @@ servers:
default: '8186'
channels:
'channels/{channelID}/messages/{subtopic}':
'm/{domainPrefix}/c/{channelPrefix}/{subtopic}':
parameters:
channelID:
$ref: '#/components/parameters/channelID'
domainPrefix:
$ref: '#/components/parameters/domainPrefix'
in: path
required: true
channelPrefix:
$ref: '#/components/parameters/channelPrefix'
in: path
required: true
subtopic:
@@ -125,11 +129,14 @@ components:
```
parameters:
channelID:
description: Channel ID connected to the Client ID defined in the username.
domainPrefix:
description: ID or route of the domain associated with the channel and client.
schema:
type: string
channelPrefix:
description: ID or route of the channel connected to the Client ID defined in the username.
schema:
type: string
format: uuid
subtopic:
description: Arbitrary message subtopic.
schema:
+5
View File
@@ -0,0 +1,5 @@
# SuperMQ OpenAPI Specification
This folder contains an OpenAPI specifications for SuperMQ API.
View specification in Swagger UI at [docs.api.supermq.abstractmachines.fr](https://docs.api.supermq.abstractmachines.fr)
+840
View File
@@ -0,0 +1,840 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.3
info:
title: SuperMQ 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 SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.18.0
servers:
- url: http://localhost:9001
- url: https://localhost:9001
tags:
- name: Keys
description: Everything about your Keys.
externalDocs:
description: Find out more about keys
url: https://docs.supermq.abstractmachines.fr/
- name: PATs
description: Everything about your Personal Access Tokens.
externalDocs:
description: Find out more about Personal Access Tokens
url: https://docs.supermq.abstractmachines.fr/
- name: Health
description: Service health check endpoint.
externalDocs:
description: Find out more about health check
url: https://docs.supermq.abstractmachines.fr/
paths:
/keys:
post:
operationId: issueKey
tags:
- Keys
summary: Issue API key
description: |
Generates a new API key. Thew new API key will
be uniquely identified by its ID.
requestBody:
$ref: "#/components/requestBodies/KeyRequest"
responses:
"201":
description: Issued new key.
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"409":
description: Failed due to using already existing ID.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/keys/{keyID}:
get:
operationId: getKey
summary: Gets API key details.
description: |
Gets API key details for the given key.
tags:
- Keys
parameters:
- $ref: "#/components/parameters/ApiKeyId"
responses:
"200":
$ref: "#/components/responses/KeyRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"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"
/pats:
post:
operationId: createPAT
tags:
- PATs
summary: Create a new Personal Access Token
description: |
Creates a new Personal Access Token (PAT) for the authenticated user.
requestBody:
$ref: "#/components/requestBodies/CreatePATRequest"
responses:
"201":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listPATs
tags:
- PATs
summary: List all Personal Access Tokens
description: |
Lists all Personal Access Tokens (PATs) for the authenticated user.
parameters:
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
responses:
"200":
$ref: "#/components/responses/PATsPageRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: clearAllPATs
tags:
- PATs
summary: Remove all Personal Access Tokens
description: |
Removes all Personal Access Tokens (PATs) for the authenticated user.
responses:
"200":
description: All PATs removed successfully.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}:
get:
operationId: retrievePAT
tags:
- PATs
summary: Retrieve a Personal Access Token
description: |
Retrieves details of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
responses:
"200":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: deletePAT
tags:
- PATs
summary: Delete a Personal Access Token
description: |
Deletes a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
responses:
"204":
description: PAT deleted successfully.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/name:
patch:
operationId: updatePATName
tags:
- PATs
summary: Update Personal Access Token name
description: |
Updates the name of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/UpdatePATNameRequest"
responses:
"202":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/description:
patch:
operationId: updatePATDescription
tags:
- PATs
summary: Update Personal Access Token description
description: |
Updates the description of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/UpdatePATDescriptionRequest"
responses:
"202":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/secret/reset:
patch:
operationId: resetPATSecret
tags:
- PATs
summary: Reset Personal Access Token secret
description: |
Resets the secret of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/ResetPATSecretRequest"
responses:
"200":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/secret/revoke:
patch:
operationId: revokePATSecret
tags:
- PATs
summary: Revoke Personal Access Token secret
description: |
Revokes the secret of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
responses:
"204":
description: PAT secret revoked successfully.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/scope:
get:
operationId: listScopes
tags:
- PATs
summary: List scopes for a Personal Access Token
description: |
Lists all scopes for a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
responses:
"200":
$ref: "#/components/responses/ScopesPageRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: clearAllScopes
tags:
- PATs
summary: Remove all scopes from a Personal Access Token
description: |
Removes all scopes from a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
responses:
"200":
description: All scopes removed successfully.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/scope/add:
patch:
operationId: addScope
tags:
- PATs
summary: Add scope to a Personal Access Token
description: |
Adds a scope to a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/AddScopeRequest"
responses:
"200":
description: Scope added successfully.
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"422":
description: Database cannot process the request.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/scope/remove:
patch:
operationId: removeScope
tags:
- PATs
summary: Remove scope from a Personal Access Token
description: |
Removes a scope from a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/RemoveScopeRequest"
responses:
"200":
description: Scope removed successfully.
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- Health
security: []
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
PAT:
type: object
properties:
id:
type: string
format: uuid
example: "c5747f2f-2a7c-4fe1-b41a-51a5ae290945"
description: Personal Access Token unique identifier
user_id:
type: string
format: uuid
example: "9118de62-c680-46b7-ad0a-21748a52833a"
description: User ID of the PAT owner
name:
type: string
example: "My PAT"
description: Name of the Personal Access Token
description:
type: string
example: "Token for automation"
description: Description of the Personal Access Token
secret:
type: string
example: "pat_1234567890abcdef"
description: Secret value of the Personal Access Token
issued_at:
type: string
format: date-time
example: "2019-11-26T13:31:52Z"
description: Time when the PAT was issued
expires_at:
type: string
format: date-time
example: "2020-11-26T13:31:52Z"
description: Time when the PAT expires
updated_at:
type: string
format: date-time
example: "2019-11-26T13:31:52Z"
description: Time when the PAT was last updated
last_used_at:
type: string
format: date-time
example: "2019-11-26T13:31:52Z"
description: Time when the PAT was last used
revoked:
type: boolean
example: false
description: Whether the PAT is revoked
revoked_at:
type: string
format: date-time
example: "2019-11-26T13:31:52Z"
description: Time when the PAT was revoked
PATsPage:
type: object
properties:
total:
type: integer
example: 10
description: Total number of PATs
offset:
type: integer
example: 0
description: Number of items to skip during retrieval
limit:
type: integer
example: 10
description: Size of the subset to retrieve
pats:
type: array
items:
$ref: "#/components/schemas/PAT"
description: List of Personal Access Tokens
Scope:
type: object
properties:
id:
type: string
format: uuid
example: "c5747f2f-2a7c-4fe1-b41a-51a5ae290945"
description: Scope unique identifier
pat_id:
type: string
format: uuid
example: "9118de62-c680-46b7-ad0a-21748a52833a"
description: PAT ID this scope belongs to
optional_domain_id:
type: string
format: uuid
example: "bb7edb32-2eac-4aad-aebe-ed96fe073879"
description: Optional domain ID for the scope
entity_type:
type: string
enum: [groups, channels, clients, domains, users, dashboards, messages]
example: "groups"
description: Type of entity the scope applies to
entity_id:
type: string
example: "*"
description: ID of the entity the scope applies to. '*' means all entities of the specified type.
operation:
type: string
enum: [create, read, list, update, delete, share, unshare, publish, subscribe]
example: "read"
description: Operation allowed by this scope
ScopesPage:
type: object
properties:
total:
type: integer
example: 10
description: Total number of scopes
offset:
type: integer
example: 0
description: Number of items to skip during retrieval
limit:
type: integer
example: 10
description: Size of the subset to retrieve
scopes:
type: array
items:
$ref: "#/components/schemas/Scope"
description: List of scopes
Key:
type: object
properties:
id:
type: string
format: uuid
example: "c5747f2f-2a7c-4fe1-b41a-51a5ae290945"
description: API key unique identifier
issuer_id:
type: string
format: uuid
example: "9118de62-c680-46b7-ad0a-21748a52833a"
description: In ID of the entity that issued the token.
type:
type: integer
example: 0
description: API key type. Keys of different type are processed differently.
subject:
type: string
format: string
example: "test@example.com"
description: User's email or service identifier of API key subject.
issued_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the key is generated.
expires_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the Key expires. If this field is missing,
that means that Key is valid indefinitely.
parameters:
PatID:
name: patID
description: Personal Access Token ID.
in: path
schema:
type: string
format: uuid
required: true
DomainID:
name: domainID
description: Unique domain identifier.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
Status:
name: status
description: Domain status.
in: query
schema:
type: string
default: enabled
required: false
example: enabled
DomainName:
name: name
description: Domain's name.
in: query
schema:
type: string
required: false
example: "domainName"
Permission:
name: permission
description: permission.
in: query
schema:
type: string
required: false
example: "edit"
ApiKeyId:
name: keyID
description: API Key ID.
in: path
schema:
type: string
format: uuid
required: true
Limit:
name: limit
description: Size of the subset to retrieve.
in: query
schema:
type: integer
default: 10
maximum: 100
minimum: 1
required: false
Offset:
name: offset
description: Number of items to skip during retrieval.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
Metadata:
name: metadata
description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
in: query
required: false
schema:
type: object
additionalProperties: {}
Type:
name: type
description: The type of the API Key.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
Subject:
name: subject
description: The subject of an API Key
in: query
schema:
type: string
required: false
requestBodies:
CreatePATRequest:
description: JSON-formatted document describing PAT creation request.
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
example: "My PAT"
description: Name of the Personal Access Token
description:
type: string
example: "Token for automation"
description: Description of the Personal Access Token
duration:
type: string
example: "30d"
description: Duration for which the PAT is valid. Format is a duration string (e.g. "30d", "24h", "1y").
UpdatePATNameRequest:
description: JSON-formatted document describing PAT name update request.
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
example: "New PAT Name"
description: New name for the Personal Access Token
UpdatePATDescriptionRequest:
description: JSON-formatted document describing PAT description update request.
required: true
content:
application/json:
schema:
type: object
required:
- description
properties:
description:
type: string
example: "New PAT Description"
description: New description for the Personal Access Token
ResetPATSecretRequest:
description: JSON-formatted document describing PAT secret reset request.
required: true
content:
application/json:
schema:
type: object
properties:
duration:
type: string
example: "30d"
description: Duration for which the new PAT secret is valid. Format is a duration string (e.g. "30d", "24h", "1y").
AddScopeRequest:
description: JSON-formatted document describing add scope request.
required: true
content:
application/json:
schema:
type: object
required:
- scopes
properties:
scopes:
type: array
items:
$ref: "#/components/schemas/Scope"
description: List of scopes to add
RemoveScopeRequest:
description: JSON-formatted document describing remove scope request.
required: true
content:
application/json:
schema:
type: object
required:
- scopes_id
properties:
scopes_id:
type: array
items:
type: string
format: uuid
description: List of scope IDs to remove
KeyRequest:
description: JSON-formatted document describing key request.
required: true
content:
application/json:
schema:
type: object
properties:
type:
type: integer
example: 0
description: API key type. Keys of different type are processed differently.
duration:
type: number
format: integer
example: 23456
description: Number of seconds issued token is valid for.
responses:
PATRes:
description: Personal Access Token data.
content:
application/json:
schema:
$ref: "#/components/schemas/PAT"
PATsPageRes:
description: Page of Personal Access Tokens.
content:
application/json:
schema:
$ref: "#/components/schemas/PATsPage"
ScopesPageRes:
description: Page of scopes.
content:
application/json:
schema:
$ref: "#/components/schemas/ScopesPage"
ServiceError:
description: Unexpected server-side error occurred.
KeyRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Key"
links:
revoke:
operationId: revokeKey
parameters:
keyID: $response.body#/id
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yaml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
@@ -13,7 +13,7 @@ info:
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
version: 0.18.0
servers:
- url: http://localhost:9005
@@ -50,7 +50,7 @@ paths:
security:
- bearerAuth: []
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
responses:
"201":
$ref: "#/components/responses/ChannelCreateRes"
@@ -84,11 +84,23 @@ paths:
security:
- bearerAuth: []
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Order"
- $ref: "#/components/parameters/Direction"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/Status"
- $ref: "#/components/parameters/ChannelName"
- $ref: "#/components/parameters/ID"
- $ref: "./schemas/roles.yaml#/components/parameters/ActionsQuery"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleIDQuery"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleNameQuery"
- $ref: "#/components/parameters/AccessType"
- $ref: "#/components/parameters/OnlyTotal"
- $ref: "#/components/parameters/Client"
- $ref: "#/components/parameters/Group"
- $ref: "#/components/parameters/User"
responses:
"200":
$ref: "#/components/responses/ChannelPageRes"
@@ -118,7 +130,7 @@ paths:
security:
- bearerAuth: []
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
responses:
"201":
$ref: "#/components/responses/ChannelsCreateRes"
@@ -148,7 +160,7 @@ paths:
tags:
- Channels
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
security:
- bearerAuth: []
@@ -178,7 +190,7 @@ paths:
tags:
- Channels
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
security:
- bearerAuth: []
@@ -211,7 +223,7 @@ paths:
tags:
- Channels
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
security:
- bearerAuth: []
@@ -240,7 +252,7 @@ paths:
tags:
- Channels
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
security:
- bearerAuth: []
@@ -275,7 +287,7 @@ paths:
tags:
- Channels
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
security:
- bearerAuth: []
@@ -306,7 +318,7 @@ paths:
tags:
- Channels
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
security:
- bearerAuth: []
@@ -337,7 +349,7 @@ paths:
tags:
- Channels
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
requestBody:
$ref: "#/components/requestBodies/ChannelParentGroupReq"
@@ -367,7 +379,7 @@ paths:
tags:
- Channels
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
requestBody:
$ref: "#/components/requestBodies/ChannelParentGroupReq"
@@ -397,7 +409,7 @@ paths:
Connect clients specified by IDs to channels specified by IDs.
Channel and client are owned by user identified using the provided access token.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
tags:
- Connections
requestBody:
@@ -430,7 +442,7 @@ paths:
Disconnect clients specified by IDs from channels specified by IDs.
Channel and client are owned by user identified using the provided access token.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
tags:
- Connections
requestBody:
@@ -454,7 +466,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/channels/{chanID}/connect:
post:
operationId: connectClientsToChannel
@@ -464,7 +476,7 @@ paths:
tags:
- Connections
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
requestBody:
$ref: "#/components/requestBodies/ChannelConnReq"
@@ -493,7 +505,7 @@ paths:
tags:
- Connections
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/chanID"
requestBody:
$ref: "#/components/requestBodies/ChannelConnReq"
@@ -534,14 +546,14 @@ components:
type: string
example: channelName
description: Free-form channel name. Channel name is unique on the given hierarchy level.
description:
type: string
example: long channel description
description: Channel description, free form text.
parent_id:
type: string
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Id of parent channel, it must be existing channel.
route:
type: string
example: channelRoute
description: Channel route.
metadata:
type: object
example: { "location": "example" }
@@ -557,7 +569,7 @@ components:
ParentGroupReqObj:
type: object
properties:
parent_group_id:
parent_group_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
@@ -587,10 +599,10 @@ components:
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Channel parent identifier.
description:
route:
type: string
example: long channel description
description: Channel description, free form text.
example: channelRoute
description: Channel route.
metadata:
type: object
example: { "role": "general" }
@@ -655,10 +667,6 @@ components:
type: string
example: channelName
description: Free-form channel name. Channel name is unique on the given hierarchy level.
description:
type: string
example: long description but not too long
description: Channel description, free form text.
metadata:
type: object
example: { "role": "general" }
@@ -666,8 +674,7 @@ components:
required:
- name
- metadata
- description
ChannelUpdateTags:
type: object
properties:
@@ -817,7 +824,7 @@ components:
format: uuid
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
Metadata:
name: metadata
description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
@@ -849,16 +856,94 @@ components:
minimum: 0
required: false
example: "0"
Order:
name: order
description: Field by which to order the results
in: query
schema:
type: string
required: false
example: created_at
Connected:
name: connected
description: Connection state of the subset to retrieve.
Direction:
name: dir
description: Direction of ordering the results.
in: query
schema:
type: string
enum:
- asc
- desc
required: false
example: desc
ID:
name: id
description: List channels with the given ID.
in: query
schema:
type: string
format: uuid
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
AccessType:
name: access_type
description: Type of access the user has on the channel.
in: query
schema:
type: string
enum:
- direct
- domain
- indirect
- indirect_group
required: false
example: direct
OnlyTotal:
name: only_total
description: If true, the response will contain only the total number of channels that match the query parameters.
in: query
schema:
type: boolean
default: true
default: false
required: false
Client:
name: client
description: If provided lists channels that a client with the provided ID is connected to.
in: query
schema:
type: string
format: uuid
minLength: 36
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
Group:
name: group
description: If provided lists channels belonging to a group with the provided ID.
in: query
schema:
type: string
format: uuid
minLength: 36
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
User:
name: user
description: If provided lists channels associated with a user with the provided ID. Only available for admin users.
in: query
schema:
type: string
format: uuid
minLength: 36
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
requestBodies:
ChannelCreateReq:
description: JSON-formatted document describing the new channel to be registered
@@ -867,7 +952,7 @@ components:
application/json:
schema:
$ref: "#/components/schemas/ChannelReqObj"
ChannelsCreateReq:
description: JSON-formatted document describing the new channels to be registered
required: true
@@ -885,15 +970,15 @@ components:
application/json:
schema:
$ref: "#/components/schemas/ChannelUpdate"
ChannelUpdateTagsReq:
description: JSON-formated document describing the tags of channel to be updated.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ChannelUpdate"
$ref: "#/components/schemas/ChannelUpdateTags"
ChannelParentGroupReq:
description: JSON-formated document describing the parent group to be set to or removed from a channel.
required: true
@@ -909,7 +994,7 @@ components:
application/json:
schema:
$ref: "#/components/schemas/ConnectionReqSchema"
ChannelConnReq:
description: JSON-formatted document describing the new connection.
required: true
@@ -936,18 +1021,6 @@ components:
operationId: getChannel
parameters:
chanID: $response.body#/id
get_clients:
operationId: listClientsInaChannel
parameters:
chanID: $response.body#/id
get_users:
operationId: listChannelsConnectedToUser
parameters:
memberID: $response.body#/id
get_groups:
operationId: listChannelsConnectedToGroup
parameters:
memberID: $response.body#/id
update:
operationId: updateChannel
parameters:
@@ -960,23 +1033,7 @@ components:
operationId: enableChannel
parameters:
chanID: $response.body#/id
assign_users:
operationId: assignUsersToChannel
parameters:
chanID: $response.body#/id
unassign_users:
operationId: unassignUsersFromChannel
parameters:
chanID: $response.body#/id
assign_groups:
operationId: assignGroupsToChannel
parameters:
chanID: $response.body#/id
unassign_groups:
operationId: unassignGroupsFromChannel
parameters:
chanID: $response.body#/id
ChannelsCreateRes:
description: Registered new channels.
headers:
@@ -996,18 +1053,6 @@ components:
operationId: getChannel
parameters:
chanID: $response.body#/id
get_clients:
operationId: listClientsInaChannel
parameters:
chanID: $response.body#/id
get_users:
operationId: listChannelsConnectedToUser
parameters:
memberID: $response.body#/id
get_groups:
operationId: listChannelsConnectedToGroup
parameters:
memberID: $response.body#/id
update:
operationId: updateChannel
parameters:
@@ -1020,22 +1065,6 @@ components:
operationId: enableChannel
parameters:
chanID: $response.body#/id
assign_users:
operationId: assignUsersToChannel
parameters:
chanID: $response.body#/id
unassign_users:
operationId: unassignUsersFromChannel
parameters:
chanID: $response.body#/id
assign_groups:
operationId: assignGroupsToChannel
parameters:
chanID: $response.body#/id
unassign_groups:
operationId: unassignGroupsFromChannel
parameters:
chanID: $response.body#/id
ChannelRes:
description: Data retrieved.
@@ -1044,32 +1073,24 @@ components:
schema:
$ref: "#/components/schemas/Channel"
links:
get_clients:
operationId: listClientsInaChannel
update:
operationId: updateChannel
parameters:
chanID: $response.body#/id
get_users:
operationId: listChannelsConnectedToUser
parameters:
memberID: $response.body#/id
get_groups:
operationId: listChannelsConnectedToGroup
parameters:
memberID: $response.body#/id
assign_users:
operationId: assignUsersToChannel
disable:
operationId: disableChannel
parameters:
chanID: $response.body#/id
unassign_users:
operationId: unassignUsersFromChannel
enable:
operationId: enableChannel
parameters:
chanID: $response.body#/id
assign_groups:
operationId: assignGroupsToChannel
set_parent_group:
operationId: setChannelParentGroup
parameters:
chanID: $response.body#/id
unassign_groups:
operationId: unassignGroupsFromChannel
remove_parent_group:
operationId: removeChannelParentGroup
parameters:
chanID: $response.body#/id
@@ -13,7 +13,7 @@ info:
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
version: 0.18.0
servers:
- url: http://localhost:9006
@@ -28,8 +28,8 @@ tags:
- name: Roles
description: All operations involving roles for clients
externalDocs:
description: Find out more about roles
url: https://docs.supermq.abstractmachines.fr/
description: Find out more about roles
url: https://docs.supermq.abstractmachines.fr/
- name: Health
description: Health check operations
externalDocs:
@@ -47,7 +47,7 @@ paths:
Adds new client to the list of clients owned by user identified using
the provided access token.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/ClientCreateReq"
responses:
@@ -81,13 +81,25 @@ paths:
dataset is consumed either by making subsequent requests, or by
increasing the subset size of the initial request.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Order"
- $ref: "#/components/parameters/Direction"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/Status"
- $ref: "#/components/parameters/ClientName"
- $ref: "#/components/parameters/Tags"
- $ref: "#/components/parameters/ID"
- $ref: "./schemas/roles.yaml#/components/parameters/ActionsQuery"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleIDQuery"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleNameQuery"
- $ref: "#/components/parameters/AccessType"
- $ref: "#/components/parameters/OnlyTotal"
- $ref: "#/components/parameters/Channel"
- $ref: "#/components/parameters/ConnectionType"
- $ref: "#/components/parameters/Group"
- $ref: "#/components/parameters/User"
security:
- bearerAuth: []
responses:
@@ -115,7 +127,7 @@ paths:
Adds a list of new clients to the list of clients owned by user identified using
the provided access token.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
tags:
- Clients
requestBody:
@@ -147,7 +159,7 @@ paths:
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
security:
- bearerAuth: []
@@ -177,7 +189,7 @@ paths:
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
requestBody:
$ref: "#/components/requestBodies/ClientUpdateReq"
@@ -210,7 +222,7 @@ paths:
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
security:
- bearerAuth: []
@@ -238,7 +250,7 @@ paths:
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
requestBody:
$ref: "#/components/requestBodies/ClientUpdateTagsReq"
@@ -270,7 +282,7 @@ paths:
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
requestBody:
$ref: "#/components/requestBodies/ClientUpdateSecretReq"
@@ -305,7 +317,7 @@ paths:
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
security:
- bearerAuth: []
@@ -336,7 +348,7 @@ paths:
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
security:
- bearerAuth: []
@@ -367,7 +379,7 @@ paths:
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
requestBody:
$ref: "#/components/requestBodies/ClientParentGroupReq"
@@ -397,7 +409,7 @@ paths:
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
requestBody:
$ref: "#/components/requestBodies/ClientParentGroupReq"
@@ -419,42 +431,6 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/users/{userID}/clients:
get:
operationId: listUserClients
summary: List clients asssociated with a user.
description: |
Lists clients associated with a user identified by the user ID.
tags:
- Clients
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "users.yml#/components/parameters/UserID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/Status"
- $ref: "#/components/parameters/ClientName"
- $ref: "#/components/parameters/Tags"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/ClientPageRes"
"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}/clients/{clientID}/roles:
post:
operationId: createClientRole
@@ -464,15 +440,15 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/CreateRoleReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/CreateRoleReq"
security:
- bearerAuth: []
responses:
"201":
$ref: "./schemas/roles.yml#/components/responses/CreateRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/CreateRoleRes"
"400":
description: Failed due to malformed client's ID.
"401":
@@ -485,7 +461,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listClientRoles
tags:
@@ -497,7 +473,7 @@ paths:
dataset is consumed either by making subsequent requests, or by
increasing the subset size of the initial request.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
@@ -505,7 +481,7 @@ paths:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListRolesRes"
$ref: "./schemas/roles.yaml#/components/responses/ListRolesRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -520,7 +496,37 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/{clientID}/roles/{roleName}:
/{domainID}/clients/{clientID}/roles/members:
get:
operationId: getClientMembers
tags:
- Roles
summary: Retrieves client members from all roles.
description: |
Retrieves members from role for the specific client.
parameters:
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yaml#/components/responses/ListEntityMembersRes"
"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}/clients/{clientID}/roles/{roleID}:
get:
operationId: getClientRole
tags:
@@ -529,14 +535,14 @@ paths:
description: |
Retrieves a specific client role that is identified by the role name.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/GetRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/GetRoleRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -550,7 +556,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
put:
operationId: updateClientRole
summary: Updates client role.
@@ -559,16 +565,16 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/UpdateRoleReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/UpdateRoleReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/GetRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/GetRoleRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -582,7 +588,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: deleteClientRole
summary: Deletes client role.
@@ -591,9 +597,9 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
@@ -612,8 +618,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/{clientID}/roles/{roleName}/actions:
/{domainID}/clients/{clientID}/roles/{roleID}/actions:
post:
operationId: addClientRoleAction
summary: Adds a role action for a client role.
@@ -622,16 +628,16 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleActionsReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleActionsReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/AddRoleActionsRes"
$ref: "./schemas/roles.yaml#/components/responses/AddRoleActionsRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -645,23 +651,23 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listClientRoleActions
tags:
- Roles
summary: Lists client role actions.
description: |
Retrieves a list of client role actions.
Retrieves a list of client role actions.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListRoleActionsRes"
$ref: "./schemas/roles.yaml#/components/responses/ListRoleActionsRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -675,8 +681,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/{clientID}/roles/{roleName}/actions/delete:
/{domainID}/clients/{clientID}/roles/{roleID}/actions/delete:
post:
operationId: deleteClientRoleAction
summary: Deletes role actions for a client role.
@@ -685,11 +691,11 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleActionsReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleActionsReq"
security:
- bearerAuth: []
responses:
@@ -708,8 +714,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/{clientID}/roles/{roleName}/actions/delete-all:
/{domainID}/clients/{clientID}/roles/{roleID}/actions/delete-all:
post:
operationId: deleteAllClientRoleActions
summary: Deletes all role actions for a client role.
@@ -718,9 +724,9 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
@@ -739,8 +745,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/{clientID}/roles/{roleName}/members:
/{domainID}/clients/{clientID}/roles/{roleID}/members:
post:
operationId: addClientRoleMember
summary: Adds a member to a client role.
@@ -749,16 +755,16 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleMembersReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleMembersReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/AddRoleMembersRes"
$ref: "./schemas/roles.yaml#/components/responses/AddRoleMembersRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -772,23 +778,23 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listClientRoleMembers
tags:
- Roles
summary: Lists client role members.
description: |
Retrieves a list of client role members.
Retrieves a list of client role members.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListRoleMembersRes"
$ref: "./schemas/roles.yaml#/components/responses/ListRoleMembersRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -802,8 +808,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/{clientID}/roles/{roleName}/members/delete:
/{domainID}/clients/{clientID}/roles/{roleID}/members/delete:
post:
operationId: deleteClientRoleMembers
summary: Deletes members from a client role.
@@ -812,11 +818,11 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleMembersReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleMembersReq"
security:
- bearerAuth: []
responses:
@@ -835,8 +841,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/clients/{clientID}/roles/{roleName}/members/delete-all:
/{domainID}/clients/{clientID}/roles/{roleID}/members/delete-all:
post:
operationId: deleteAllClientRoleMembers
summary: Deletes all members from a client role.
@@ -845,9 +851,9 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/clientID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
@@ -874,14 +880,14 @@ paths:
- Roles
summary: Retrieves available actions.
description: |
Retrieves a list of available actions.
Retrieves a list of available actions.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListAvailableActionsRes"
$ref: "./schemas/roles.yaml#/components/responses/ListAvailableActionsRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -952,7 +958,7 @@ components:
ParentGroupReqObj:
type: object
properties:
parent_group_id:
parent_group_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
@@ -1095,9 +1101,7 @@ components:
example: 10
description: Maximum number of items to return in one page.
required:
- clients
- total
- offset
ClientUpdate:
type: object
@@ -1247,6 +1251,105 @@ components:
required: false
example: "0"
Order:
name: order
description: Field by which to order the results
in: query
schema:
type: string
required: false
example: created_at
Direction:
name: dir
description: Direction of ordering the results.
in: query
schema:
type: string
enum:
- asc
- desc
required: false
example: desc
ID:
name: id
description: List clients with the given ID.
in: query
schema:
type: string
format: uuid
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
AccessType:
name: access_type
description: Type of access the user has on the client.
in: query
schema:
type: string
enum:
- direct
- domain
- indirect
- indirect_group
required: false
example: direct
OnlyTotal:
name: only_total
description: If true, the response will contain only the total number of clients that match the query parameters.
in: query
schema:
type: boolean
default: false
required: false
Channel:
name: channel
description: If provided lists clients connected to a channel with the provided ID.
in: query
schema:
type: string
format: uuid
minLength: 36
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
ConnectionType:
name: connection_type
description: If provided with channel parameter lists clients connected to the channel with the provided connection type.
in: query
schema:
type: string
enum:
- Publish
- Subscribe
required: false
example: Publish
Group:
name: group
description: If provided lists clients belonging to a group with the provided ID.
in: query
schema:
type: string
format: uuid
minLength: 36
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
User:
name: user
description: If provided lists clients associated with a user with the provided ID. Only available for admin users.
in: query
schema:
type: string
format: uuid
minLength: 36
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
requestBodies:
ClientCreateReq:
description: JSON-formatted document describing the new client to be registered
@@ -1316,10 +1419,6 @@ components:
operationId: getClient
parameters:
clientID: $response.body#/id
get_channels:
operationId: listChannelsConnectedToClient
parameters:
clientID: $response.body#/id
update:
operationId: updateClient
parameters:
@@ -1332,14 +1431,6 @@ components:
operationId: updateClientSecret
parameters:
clientID: $response.body#/id
share:
operationId: shareClient
parameters:
clientID: $response.body#/id
unsahre:
operationId: unshareClient
parameters:
clientID: $response.body#/id
disable:
operationId: disableClient
parameters:
@@ -1355,19 +1446,6 @@ components:
application/json:
schema:
$ref: "#/components/schemas/Client"
links:
get_channels:
operationId: listChannelsConnectedToClient
parameters:
clientID: $response.body#/id
share:
operationId: shareClient
parameters:
clientID: $response.body#/id
unsahre:
operationId: unshareClient
parameters:
clientID: $response.body#/id
ClientPageRes:
description: Data retrieved.
@@ -3,17 +3,17 @@
openapi: 3.0.3
info:
title: Magistrala Domains Service
title: SuperMQ Domains Service
description: |
This is the Domains Server based on the OpenAPI 3.0 specification. It is the HTTP API for managing platform domains. 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)
- [The SuperMQ repository](https://github.com/absmach/supermq)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.15.1
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.18.0
servers:
- url: http://localhost:9003
@@ -24,17 +24,22 @@ tags:
description: CRUD operations for your domains
externalDocs:
description: Find out more about domains
url: https://docs.magistrala.abstractmachines.fr/
url: https://docs.supermq.abstractmachines.fr/
- name: Roles
description: All operations involving roles for clients
description: All operations involving roles for domains
externalDocs:
description: Find out more about roles
url: https://docs.supermq.abstractmachines.fr/
description: Find out more about roles
url: https://docs.supermq.abstractmachines.fr/
- name: Invitations
description: All operations involving invitations for domains
externalDocs:
description: Find out more about Invitations
url: https://docs.supermq.abstractmachines.fr/
- name: Health
description: Service health check endpoint.
externalDocs:
description: Find out more about health check
url: https://docs.magistrala.abstractmachines.fr/
url: https://docs.supermq.abstractmachines.fr/
paths:
/domains:
@@ -54,7 +59,7 @@ paths:
"401":
description: Missing or invalid access token provided.
"409":
description: Failed due to using an existing alias.
description: Failed due to using an existing route.
"415":
description: Missing or invalid content type.
"422":
@@ -68,10 +73,16 @@ paths:
parameters:
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Order"
- $ref: "#/components/parameters/Direction"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/Status"
- $ref: "#/components/parameters/DomainName"
- $ref: "#/components/parameters/Permission"
- $ref: "./schemas/roles.yaml#/components/parameters/ActionsQuery"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleIDQuery"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleNameQuery"
- $ref: "#/components/parameters/AccessType"
- $ref: "#/components/parameters/OnlyTotal"
tags:
- Domains
security:
@@ -118,9 +129,9 @@ paths:
$ref: "#/components/responses/ServiceError"
patch:
summary: Updates name, metadata, tags and alias of the domain.
summary: Updates name, metadata and tags of the domain.
description: |
Updates name, metadata, tags and alias of the domain.
Updates name, metadata and tags of the domain.
tags:
- Domains
parameters:
@@ -225,7 +236,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/roles:
post:
operationId: createDomainRole
@@ -235,15 +246,14 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/CreateRoleReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/CreateRoleReq"
security:
- bearerAuth: []
responses:
"201":
$ref: "./schemas/roles.yml#/components/responses/CreateRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/CreateRoleRes"
"400":
description: Failed due to malformed domain's ID.
"401":
@@ -256,7 +266,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listDomainRoles
tags:
@@ -268,7 +278,6 @@ paths:
dataset is consumed either by making subsequent requests, or by
increasing the subset size of the initial request.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
@@ -276,7 +285,7 @@ paths:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListRolesRes"
$ref: "./schemas/roles.yaml#/components/responses/ListRolesRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -291,7 +300,7 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/roles/{roleName}:
/domains/{domainID}/roles/{roleID}:
get:
operationId: getDomainRole
tags:
@@ -300,14 +309,13 @@ paths:
description: |
Retrieves a specific domain role that is identified by the role name.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/GetRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/GetRoleRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -321,7 +329,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
put:
operationId: updateDomainRole
summary: Updates domain role.
@@ -330,16 +338,15 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/UpdateRoleReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/UpdateRoleReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/GetRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/GetRoleRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -353,7 +360,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: deleteDomainRole
summary: Deletes domain role.
@@ -362,9 +369,8 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
@@ -383,8 +389,37 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/roles/{roleName}/actions:
/domain/{domainID}/roles/members:
get:
operationId: getDomainMembers
tags:
- Roles
summary: Retrieves domain members from all roles.
description: |
Retrieves members from role for the specific domain.
parameters:
- $ref: "auth.yaml#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yaml#/components/responses/ListEntityMembersRes"
"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"
/domains/{domainID}/roles/{roleID}/actions:
post:
operationId: addDomainRoleAction
summary: Adds a role action for a domain role.
@@ -393,16 +428,15 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleActionsReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleActionsReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/AddRoleActionsRes"
$ref: "./schemas/roles.yaml#/components/responses/AddRoleActionsRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -416,23 +450,22 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listDomainRoleActions
tags:
- Roles
summary: Lists domain role actions.
description: |
Retrieves a list of domain role actions.
Retrieves a list of domain role actions.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListRoleActionsRes"
$ref: "./schemas/roles.yaml#/components/responses/ListRoleActionsRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -446,8 +479,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/roles/{roleName}/actions/delete:
/domains/{domainID}/roles/{roleID}/actions/delete:
post:
operationId: deleteDomainRoleAction
summary: Deletes role actions for a domain role.
@@ -456,11 +489,10 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleActionsReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleActionsReq"
security:
- bearerAuth: []
responses:
@@ -479,8 +511,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/roles/{roleName}/actions/delete-all:
/domains/{domainID}/roles/{roleID}/actions/delete-all:
post:
operationId: deleteAllDomainRoleActions
summary: Deletes all role actions for a domain role.
@@ -489,9 +521,8 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
@@ -510,8 +541,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/roles/{roleName}/members:
/domains/{domainID}/roles/{roleID}/members:
post:
operationId: addDomainRoleMember
summary: Adds a member to a domain role.
@@ -520,16 +551,15 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleMembersReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleMembersReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/AddRoleMembersRes"
$ref: "./schemas/roles.yaml#/components/responses/AddRoleMembersRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -543,23 +573,22 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listDomainRoleMembers
tags:
- Roles
summary: Lists domain role members.
description: |
Retrieves a list of domain role members.
Retrieves a list of domain role members.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListRoleMembersRes"
$ref: "./schemas/roles.yaml#/components/responses/ListRoleMembersRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -573,8 +602,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/roles/{roleName}/members/delete:
/domains/{domainID}/roles/{roleID}/members/delete:
post:
operationId: deleteDomainRoleMembers
summary: Deletes members from a domain role.
@@ -583,11 +612,10 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleMembersReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleMembersReq"
security:
- bearerAuth: []
responses:
@@ -606,8 +634,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/roles/{roleName}/members/delete-all:
/domains/{domainID}/roles/{roleID}/members/delete-all:
post:
operationId: deleteAllDomainRoleMembers
summary: Deletes all members from a domain role.
@@ -616,9 +644,8 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
@@ -637,7 +664,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/roles/available-actions:
get:
operationId: listAvailableActions
@@ -645,14 +672,14 @@ paths:
- Roles
summary: Retrieves available actions.
description: |
Retrieves a list of available actions.
Retrieves a list of available actions.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListAvailableActionsRes"
$ref: "./schemas/roles.yaml#/components/responses/ListAvailableActionsRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -667,6 +694,193 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/invitations:
post:
operationId: sendInvitation
tags:
- Invitations
summary: Send invitation
description: |
Send invitation to user to join domain.
parameters:
- $ref: "#/components/parameters/DomainID"
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: listDomainInvitations
tags:
- Invitations
summary: List domain invitations
description: |
Retrieves a list of invitations for a given domain. Due to performance concerns, data
is retrieved in subsets. The API must ensure that the entire
dataset is consumed either by making subsequent requests, or by
increasing the subset size of the initial request.
parameters:
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/user_id"
- $ref: "#/components/parameters/InvitedBy"
- $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"
delete:
operationId: deleteInvitation
summary: Deletes a specific invitation
description: |
Deletes a specific invitation that is identified by the user ID and domain ID.
The user ID is provided in the request body.
tags:
- Invitations
parameters:
- $ref: "#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/DeleteInvitationReq"
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"
/invitations:
get:
operationId: listUserInvitations
tags:
- Invitations
summary: List user invitations
description: |
Retrieves a list of invitations for the current 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: "#/components/parameters/domain_id"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/user_id"
- $ref: "#/components/parameters/InvitedBy"
- $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.
"422":
description: Database can't process 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.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
@@ -699,13 +913,13 @@ components:
type: object
example: { "domain": "example.com" }
description: Arbitrary, object-encoded domain's data.
alias:
route:
type: string
example: domain alias
description: Domain alias.
example: domain_route
description: Domain route.
required:
- name
- alias
- route
Domain:
type: object
properties:
@@ -729,10 +943,10 @@ components:
type: object
example: { "domain": "example.com" }
description: Arbitrary, object-encoded domain's data.
alias:
route:
type: string
example: domain alias
description: Domain alias.
example: domain_route
description: Domain route.
status:
type: string
description: Domain Status
@@ -782,9 +996,7 @@ components:
example: 10
description: Maximum number of items to return in one page.
required:
- domains
- total
- offset
DomainUpdate:
type: object
properties:
@@ -803,10 +1015,107 @@ components:
type: object
example: { "domain": "example.com" }
description: Arbitrary, object-encoded domain's data.
alias:
SendInvitationReqObj:
type: object
properties:
invitee_user_id:
type: string
example: domain alias
description: Domain alias.
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: User unique identifier.
role_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Identifier for the role to be assigned to the user.
required:
- invitee_user_id
- role_id
Invitation:
type: object
properties:
invited_by:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: User unique identifier.
invitee_user_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Invitee user unique identifier.
domain_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Domain unique identifier.
role_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Role unique identifier.
role_name:
type: string
example: editor
description: Role name.
actions:
type: array
items:
type: string
example: ["read", "write"]
description: Actions allowed for the role.
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" }
parameters:
DomainID:
@@ -835,14 +1144,6 @@ components:
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.
@@ -894,6 +1195,92 @@ components:
schema:
type: string
required: false
UserID:
name: userID
description: Unique user identifier.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
user_id:
name: user_id
description: Unique user identifier.
in: query
schema:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
domain_id:
name: domain_id
description: Unique identifier for a domain.
in: query
schema:
type: string
format: uuid
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
State:
name: state
description: Invitation state.
in: query
schema:
type: string
enum:
- pending
- accepted
- all
required: false
example: accepted
Order:
name: order
description: Field by which to order the results
in: query
schema:
type: string
required: false
example: created_at
Direction:
name: dir
description: Direction of ordering the results.
in: query
schema:
type: string
enum:
- asc
- desc
required: false
example: desc
AccessType:
name: access_type
description: Type of access the user has on the domain.
in: query
schema:
type: string
enum:
- direct
- domain
- indirect
- indirect_group
required: false
example: direct
OnlyTotal:
name: only_total
description: If true, the response will contain only the total number of domains that match the query parameters.
in: query
schema:
type: boolean
default: false
required: false
requestBodies:
DomainCreateReq:
@@ -904,12 +1291,49 @@ components:
schema:
$ref: "#/components/schemas/DomainReqObj"
DomainUpdateReq:
description: JSON-formated document describing the name, alias, tags, and metadata of the domain to be updated
description: JSON-formated document describing the name, tags, and metadata of the domain to be updated
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DomainUpdate"
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
DeleteInvitationReq:
description: JSON-formatted document describing request for deleting invitation
required: true
content:
application/json:
schema:
type: object
properties:
user_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: User unique identifier.
required:
- user_id
responses:
ServiceError:
@@ -940,12 +1364,31 @@ components:
application/json:
schema:
$ref: "#/components/schemas/DomainsPage"
InvitationRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Invitation"
links:
delete:
operationId: deleteInvitation
parameters:
userID: $response.body#/user_id
domainID: $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: "./schemas/health_info.yml"
$ref: "./schemas/health_info.yaml"
securitySchemes:
bearerAuth:
@@ -13,7 +13,7 @@ info:
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
version: 0.18.0
servers:
- url: http://localhost:9004
@@ -28,8 +28,8 @@ tags:
- name: Roles
description: All operations involving roles for groups
externalDocs:
description: Find out more about roles
url: https://docs.supermq.abstractmachines.fr/
description: Find out more about roles
url: https://docs.supermq.abstractmachines.fr/
- name: Health
description: Health check operations
externalDocs:
@@ -47,7 +47,7 @@ paths:
Creates new group that can be used for grouping entities. New account will
be uniquely identified by its identity.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/GroupCreateReq"
security:
@@ -85,14 +85,23 @@ paths:
security:
- bearerAuth: []
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Order"
- $ref: "#/components/parameters/DirectionOrder"
- $ref: "#/components/parameters/Level"
- $ref: "#/components/parameters/Tree"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/GroupName"
- $ref: "#/components/parameters/ParentID"
- $ref: "#/components/parameters/RootGroup"
- $ref: "#/components/parameters/Status"
- $ref: "#/components/parameters/ID"
- $ref: "./schemas/roles.yaml#/components/parameters/ActionsQuery"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleIDQuery"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleNameQuery"
- $ref: "#/components/parameters/AccessType"
- $ref: "#/components/parameters/OnlyTotal"
responses:
"200":
$ref: "#/components/responses/GroupPageRes"
@@ -118,7 +127,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
security:
- bearerAuth: []
@@ -146,7 +155,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
security:
- bearerAuth: []
@@ -179,7 +188,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
security:
- bearerAuth: []
@@ -197,6 +206,43 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/tags:
patch:
operationId: updateGroupTags
summary: Updates group tags.
description: |
Update is performed by replacing the current resource data with values
provided in a request payload. Note that the group's ID will not be
affected.
tags:
- Groups
parameters:
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
security:
- bearerAuth: []
requestBody:
$ref: "#/components/requestBodies/GroupUpdateTagsReq"
responses:
"200":
$ref: "#/components/responses/GroupRes"
"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: Group does not exist.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/enable:
post:
operationId: enableGroup
@@ -206,7 +252,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
security:
- bearerAuth: []
@@ -239,7 +285,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
security:
- bearerAuth: []
@@ -262,7 +308,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/hierarchy:
get:
operationId: listGroupHierarchy
@@ -277,7 +323,7 @@ paths:
security:
- bearerAuth: []
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "#/components/parameters/Level"
- $ref: "#/components/parameters/Tree"
@@ -297,7 +343,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/parent:
post:
operationId: setGroupParentGroup
@@ -307,7 +353,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
requestBody:
$ref: "#/components/requestBodies/GroupParentReq"
@@ -337,7 +383,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
requestBody:
$ref: "#/components/requestBodies/GroupParentReq"
@@ -368,7 +414,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
requestBody:
$ref: "#/components/requestBodies/GroupChildrenReq"
@@ -402,7 +448,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
requestBody:
$ref: "#/components/requestBodies/GroupChildrenReq"
@@ -441,7 +487,7 @@ paths:
security:
- bearerAuth: []
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
@@ -465,7 +511,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/children/all:
delete:
operationId: removeAllChildrenGroups
@@ -475,7 +521,7 @@ paths:
tags:
- Groups
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
security:
- bearerAuth: []
@@ -508,15 +554,15 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/CreateRoleReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/CreateRoleReq"
security:
- bearerAuth: []
responses:
"201":
$ref: "./schemas/roles.yml#/components/responses/CreateRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/CreateRoleRes"
"400":
description: Failed due to malformed group's ID.
"401":
@@ -529,7 +575,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listGroupRoles
tags:
@@ -541,7 +587,7 @@ paths:
dataset is consumed either by making subsequent requests, or by
increasing the subset size of the initial request.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
@@ -549,7 +595,7 @@ paths:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListRolesRes"
$ref: "./schemas/roles.yaml#/components/responses/ListRolesRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -564,7 +610,37 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/roles/{roleName}:
/{domainID}/groups/{groupID}/roles/members:
get:
operationId: getGroupMembers
tags:
- Roles
summary: Retrieves group members from all roles.
description: |
Retrieves members from role for the specific group.
parameters:
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yaml#/components/responses/ListEntityMembersRes"
"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}/groups/{groupID}/roles/{roleID}:
get:
operationId: getGroupRole
tags:
@@ -573,14 +649,14 @@ paths:
description: |
Retrieves a specific group role that is identified by the role name.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/GetRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/GetRoleRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -594,7 +670,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
put:
operationId: updateGroupRole
summary: Updates group role.
@@ -603,16 +679,16 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/UpdateRoleReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/UpdateRoleReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/GetRoleRes"
$ref: "./schemas/roles.yaml#/components/responses/GetRoleRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -626,7 +702,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: deleteGroupRole
summary: Deletes group role.
@@ -635,9 +711,9 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
@@ -656,8 +732,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/roles/{roleName}/actions:
/{domainID}/groups/{groupID}/roles/{roleID}/actions:
post:
operationId: addGroupRoleAction
summary: Adds a role action for a group role.
@@ -666,16 +742,16 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleActionsReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleActionsReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/AddRoleActionsRes"
$ref: "./schemas/roles.yaml#/components/responses/AddRoleActionsRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -689,23 +765,23 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listGroupRoleActions
tags:
- Roles
summary: Lists group role actions.
description: |
Retrieves a list of group role actions.
Retrieves a list of group role actions.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListRoleActionsRes"
$ref: "./schemas/roles.yaml#/components/responses/ListRoleActionsRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -719,8 +795,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/roles/{roleName}/actions/delete:
/{domainID}/groups/{groupID}/roles/{roleID}/actions/delete:
post:
operationId: deleteGroupRoleAction
summary: Deletes role actions for a group role.
@@ -729,11 +805,11 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleActionsReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleActionsReq"
security:
- bearerAuth: []
responses:
@@ -752,8 +828,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/roles/{roleName}/actions/delete-all:
/{domainID}/groups/{groupID}/roles/{roleID}/actions/delete-all:
post:
operationId: deleteAllGroupRoleActions
summary: Deletes all role actions for a group role.
@@ -762,9 +838,9 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
@@ -783,8 +859,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/roles/{roleName}/members:
/{domainID}/groups/{groupID}/roles/{roleID}/members:
post:
operationId: addGroupRoleMember
summary: Adds a member to a group role.
@@ -793,16 +869,16 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleMembersReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleMembersReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/AddRoleMembersRes"
$ref: "./schemas/roles.yaml#/components/responses/AddRoleMembersRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -816,23 +892,23 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listGroupRoleMembers
tags:
- Roles
summary: Lists group role members.
description: |
Retrieves a list of group role members.
Retrieves a list of group role members.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListRoleMembersRes"
$ref: "./schemas/roles.yaml#/components/responses/ListRoleMembersRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -846,8 +922,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/roles/{roleName}/members/delete:
/{domainID}/groups/{groupID}/roles/{roleID}/members/delete:
post:
operationId: deleteGroupRoleMembers
summary: Deletes members from a group role.
@@ -856,11 +932,11 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
requestBody:
$ref: "./schemas/roles.yml#/components/requestBodies/AddRoleMembersReq"
$ref: "./schemas/roles.yaml#/components/requestBodies/AddRoleMembersReq"
security:
- bearerAuth: []
responses:
@@ -879,8 +955,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/roles/{roleName}/members/delete-all:
/{domainID}/groups/{groupID}/roles/{roleID}/members/delete-all:
post:
operationId: deleteAllGroupRoleMembers
summary: Deletes all members from a group role.
@@ -889,9 +965,9 @@ paths:
tags:
- Roles
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "./schemas/roles.yml#/components/parameters/RoleName"
- $ref: "./schemas/roles.yaml#/components/parameters/RoleID"
security:
- bearerAuth: []
responses:
@@ -918,14 +994,14 @@ paths:
- Roles
summary: Retrieves available actions.
description: |
Retrieves a list of available actions.
Retrieves a list of available actions.
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "auth.yaml#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"200":
$ref: "./schemas/roles.yml#/components/responses/ListAvailableActionsRes"
$ref: "./schemas/roles.yaml#/components/responses/ListAvailableActionsRes"
"400":
description: Failed due to malformed query parameters.
"401":
@@ -1008,6 +1084,12 @@ components:
type: string
example: long group description
description: Group description, free form text.
tags:
type: array
items:
type: string
example: ["tag1", "tag2"]
description: Group tags.
metadata:
type: object
example: { "role": "general" }
@@ -1122,10 +1204,8 @@ components:
example: 10
description: Maximum number of items to return in one page.
required:
- groups
- total
- offset
GroupsHierarchyPage:
type: object
properties:
@@ -1189,17 +1269,30 @@ components:
- metadata
- description
GroupUpdateTags:
type: object
properties:
tags:
type: array
minItems: 0
items:
type: string
example: ["tag1", "tag2"]
description: Group tags.
required:
- tags
ParentGroupReqObj:
type: object
properties:
group_id:
group_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Parent group unique identifier.
required:
- group_id
ChildrenGroupReqObj:
type: object
properties:
@@ -1271,11 +1364,14 @@ components:
Status:
name: status
description: User account status.
description: Lists groups with the given status.
in: query
schema:
type: string
default: enabled
enum:
- enabled
- disabled
- all
required: false
example: enabled
@@ -1368,7 +1464,7 @@ components:
minimum: 1
maximum: 5
required: false
StartLevel:
name: start_level
description: Level of hierarchy from which to start retrieving groups from given group id.
@@ -1376,7 +1472,7 @@ components:
schema:
type: integer
required: false
EndLevel:
name: end_level
description: Level of hierarchy up to which to retrieve groups from given group id.
@@ -1402,6 +1498,15 @@ components:
type: boolean
default: false
RootGroup:
name: root_group
description: List groups without a parent group.
in: query
schema:
type: boolean
default: false
required: false
Metadata:
name: metadata
description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
@@ -1433,6 +1538,71 @@ components:
minimum: 0
required: false
example: "0"
Order:
name: order
description: Field by which to order the results
in: query
schema:
type: string
required: false
example: created_at
DirectionOrder:
name: order
description: Direction of ordering the results.
in: query
schema:
type: string
enum:
- asc
- desc
required: false
example: desc
ID:
name: id
description: List groups with the given ID.
in: query
schema:
type: string
format: uuid
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
AccessType:
name: access_type
description: Type of access the user has on the group.
in: query
schema:
type: string
enum:
- direct
- domain
- indirect
- indirect_group
required: false
example: direct
OnlyTotal:
name: only_total
description: If true, the response will contain only the total number of groups that match the query parameters.
in: query
schema:
type: boolean
default: false
required: false
User:
name: user
description: If provided lists groups associated with a user with the provided ID. Only available for admin users.
in: query
schema:
type: string
format: uuid
minLength: 36
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
requestBodies:
GroupCreateReq:
@@ -1451,6 +1621,14 @@ components:
schema:
$ref: "#/components/schemas/GroupUpdate"
GroupUpdateTagsReq:
description: JSON-formated document describing the tags of group to be updated.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/GroupUpdateTags"
GroupParentReq:
description: JSON-formated document describing the parent group to be set to or removed from a group.
required: true
@@ -1458,7 +1636,7 @@ components:
application/json:
schema:
$ref: "#/components/schemas/ParentGroupReqObj"
GroupChildrenReq:
description: JSON-formated document describing the children groups to be added to a group.
required: true
@@ -1486,21 +1664,9 @@ components:
parameters:
groupID: $response.body#/id
get_children:
operationId: listChildren
operationId: listChildrenGroups
parameters:
groupID: $response.body#/id
get_parent:
operationId: listParents
parameters:
groupID: $response.body#/id
get_channels:
operationId: listGroupsInChannel
parameters:
memberID: $response.body#/id
get_users:
operationId: listGroupsByUser
parameters:
memberID: $response.body#/id
update:
operationId: updateGroup
parameters:
@@ -1513,14 +1679,6 @@ components:
operationId: enableGroup
parameters:
groupID: $response.body#/id
assign:
operationId: assignUser
parameters:
groupID: $response.body#/id
unassign:
operationId: unassignUser
parameters:
groupID: $response.body#/id
GroupRes:
description: Data retrieved.
@@ -1530,27 +1688,19 @@ components:
$ref: "#/components/schemas/Group"
links:
get_children:
operationId: listChildren
operationId: listChildrenGroups
parameters:
groupID: $response.body#/id
get_parent:
operationId: listParents
update:
operationId: updateGroup
parameters:
groupID: $response.body#/id
get_channels:
operationId: listGroupsInChannel
parameters:
memberID: $response.body#/id
get_users:
operationId: listGroupsByUser
parameters:
memberID: $response.body#/id
assign:
operationId: assignUser
disable:
operationId: disableGroup
parameters:
groupID: $response.body#/id
unassign:
operationId: unassignUser
enable:
operationId: enableGroup
parameters:
groupID: $response.body#/id
@@ -13,7 +13,7 @@ info:
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
version: 0.18.0
servers:
- url: http://localhost:8008
@@ -27,7 +27,7 @@ tags:
url: https://docs.supermq.abstractmachines.fr/
paths:
/channels/{id}/messages:
/m/{domainPrefix}/c/{channelPrefix}:
post:
summary: Sends message to the communication channel
description: |
@@ -36,7 +36,8 @@ paths:
tags:
- messages
parameters:
- $ref: "#/components/parameters/ID"
- $ref: "#/components/parameters/domainPrefix"
- $ref: "#/components/parameters/channelPrefix"
requestBody:
$ref: "#/components/requestBodies/MessageReq"
responses:
@@ -129,13 +130,21 @@ components:
$ref: "#/components/schemas/SenMLRecord"
parameters:
ID:
name: id
description: Unique channel identifier.
domainPrefix:
name: domainPrefix
description: ID or route of the domain associated with the channel and client.
in: path
schema:
type: string
format: uuid
example: mydomain
required: true
channelPrefix:
name: channelPrefix
description: ID or route of the channel connected to the client.
in: path
schema:
type: string
example: mychannel
required: true
requestBodies:
@@ -161,7 +170,7 @@ components:
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yml"
$ref: "./schemas/health_info.yaml"
securitySchemes:
bearerAuth:
@@ -13,7 +13,7 @@ info:
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
version: 0.18.0
servers:
- url: http://localhost:9021
@@ -65,6 +65,39 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/journal/client/{clientID}/telemetry:
get:
tags:
- journal-log
summary: View client telemetry
description: |
Retrieves telemetry data for a specific client within a domain.
This includes connection status, messages sent/received, and other metrics.
parameters:
- $ref: "#/components/parameters/domain_id"
- $ref: '#/components/parameters/client_id'
security:
- bearerAuth: []
responses:
"200":
description: Client telemetry data retrieved successfully
content:
application/json:
schema:
$ref: "#/components/schemas/Telemetry"
"400":
description: Failed due to malformed request parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: Client not found.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/journal/{entityType}/{id}:
get:
tags:
@@ -119,6 +152,45 @@ paths:
components:
schemas:
Telemetry:
type: object
properties:
client_id:
type: string
format: uuid
description: Unique identifier of the client
example: "bb7edb32-2eac-4aad-aebe-ed96fe073879"
domain_id:
type: string
format: uuid
description: Unique identifier of the domain
example: "29d425c8-542b-4614-8a4d-a5951945d720"
subscriptions:
type: integer
format: int64
description: Number of active subscriptions for the client
example: 5
inbound_messages:
type: integer
format: int64
description: Number of messages received by the client
example: 1234567
outbound_messages:
type: integer
format: int64
description: Number of messages sent by the client
example: 987654
first_seen:
type: string
format: date-time
description: Timestamp when the client was first seen
example: "2024-01-11T10:00:00.000Z"
last_seen:
type: string
format: date-time
description: Timestamp when the client was last seen
example: "2024-01-11T12:05:07.449053Z"
Journal:
type: object
properties:
@@ -195,9 +267,19 @@ components:
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
client_id:
name: clientID
description: Unique identifier for a client
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, client, etc.entityType
description: Type of entity, e.g. group, client, channel.
in: path
schema:
type: string
@@ -220,7 +302,7 @@ components:
id:
name: id
description: Unique identifier for an entity, e.g. group, channel or thing. Used together with entity_type.
description: Unique identifier for an entity, e.g. group, channel or client. Used together with entity_type.
in: path
schema:
type: string
@@ -323,7 +405,7 @@ components:
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yml"
$ref: "./schemas/health_info.yaml"
ServiceError:
description: Unexpected server-side error occurred.
@@ -11,7 +11,7 @@ properties:
version:
type: string
description: Service version.
example: v0.14.0
example: v0.18.0
commit:
type: string
description: Service commit hash.
@@ -6,12 +6,12 @@ components:
NewRole:
type: object
properties:
role_id:
id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Role unique identifier.
role_name:
name:
type: string
description: Role's name.
example: "roleName"
@@ -44,12 +44,12 @@ components:
Role:
type: object
properties:
role_id:
id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Role unique identifier.
role_name:
name:
type: string
description: Role's name.
example: "roleName"
@@ -78,11 +78,11 @@ components:
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the channel was created.
CreateRoleObj:
type: object
properties:
role_name:
name:
type: string
description: Role's name.
example: "roleName"
@@ -94,7 +94,7 @@ components:
example:
[
"read",
"update",
"update",
]
optional_members:
type: array
@@ -107,7 +107,7 @@ components:
"5dc1ce4b-7cc9-4f12-98a6-9d74cc4980bb",
"c01ed106-e52d-4aa4-bed3-39f360177cfa",
]
UpdateRoleObj:
type: object
properties:
@@ -135,6 +135,31 @@ components:
example: 10
description: Maximum number of items to return in one page.
EntityMembersPage:
type: object
properties:
groups:
type: array
minItems: 0
uniqueItems: true
items:
$ref: "#/components/schemas/EntityMembersObj"
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:
- groups
- total
- offset
RoleActionsObj:
type: object
properties:
@@ -146,9 +171,9 @@ components:
example:
[
"read",
"update",
"update",
]
RoleMembersObj:
type: object
properties:
@@ -162,7 +187,58 @@ components:
"5dc1ce4b-7cc9-4f12-98a6-9d74cc4980bb",
"c01ed106-e52d-4aa4-bed3-39f360177cfa",
]
EntityMembersObj:
type: object
properties:
members:
type: array
description: List of members with assigned roles and actions.
items:
type: object
properties:
id:
type: string
format: uuid
description: Unique identifier of the member.
roles:
type: array
description: List of roles assigned to the member.
items:
type: object
properties:
id:
type: string
format: uuid
description: Unique identifier of the role.
name:
type: string
description: Name of the role.
actions:
type: array
description: List of actions the member can perform.
items:
type: string
access_type:
type: string
description: Type of access granted.
enum: [read, write, admin] # Adjust based on your actual access types.
example:
members:
- id: "5dc1ce4b-7cc9-4f12-98a6-9d74cc4980bb"
roles:
- id: "a1b2c3d4-e5f6-7890-1234-56789abcdef0"
name: "Admin"
actions: ["create", "update", "delete"]
access_type: "admin"
- id: "c01ed106-e52d-4aa4-bed3-39f360177cfa"
roles:
- id: "b2c3d4e5-f678-9012-3456-789abcdef012"
name: "Editor"
actions: ["read", "update"]
access_type: "write"
AvailableActionsObj:
type: object
properties:
@@ -176,7 +252,7 @@ components:
"read",
"update",
]
parameters:
RoleName:
name: roleName
@@ -186,6 +262,39 @@ components:
type: string
required: true
example: "roleName"
RoleID:
name: roleID
description: Role ID.
in: path
schema:
type: string
required: true
example: "roleID"
RoleIDQuery:
name: role_id
description: Filter by role ID.
in: query
schema:
type: string
format: uuid
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
RoleNameQuery:
name: role_name
description: Filter by role name.
in: query
schema:
type: string
required: false
example: admin
ActionsQuery:
name: actions
description: Filter by actions. Multiple actions can be specified separated by comma.
in: query
schema:
type: string
required: false
example: "action1,action2"
requestBodies:
CreateRoleReq:
@@ -193,17 +302,17 @@ components:
required: true
content:
application/json:
schema:
schema:
$ref: '#/components/schemas/CreateRoleObj'
UpdateRoleReq:
description: JSON- formatted object decsribing a role to be updated.
required: true
content:
application/json:
schema:
schema:
$ref: '#/components/schemas/UpdateRoleObj'
AddRoleActionsReq:
description: JSON- formatted object decsribing an action to be added to a role.
required: true
@@ -241,7 +350,7 @@ components:
application/json:
schema:
$ref: '#/components/schemas/Role'
AddRoleActionsRes:
description: Action added to role successfully.
content:
@@ -255,14 +364,14 @@ components:
application/json:
schema:
$ref: '#/components/schemas/RoleActionsObj'
AddRoleMembersRes:
description: Member added to role successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/RoleMembersObj'
ListRoleMembersRes:
description: Role members retrieved successfully.
content:
@@ -276,3 +385,11 @@ components:
application/json:
schema:
$ref: '#/components/schemas/AvailableActionsObj'
ListEntityMembersRes:
description: Entity members retrieved successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/EntityMembersObj'
@@ -13,7 +13,7 @@ info:
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
version: 0.18.0
servers:
- url: http://localhost:9018
@@ -417,7 +417,7 @@ components:
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yml"
$ref: "./schemas/health_info.yaml"
securitySchemes:
bearerAuth:
@@ -13,7 +13,7 @@ info:
license:
name: Apache 2.0
url: https://github.com/absmach/supermq/blob/main/LICENSE
version: 0.15.1
version: 0.18.0
servers:
- url: http://localhost:9002
@@ -43,6 +43,7 @@ paths:
be uniquely identified by its email address.
requestBody:
$ref: "#/components/requestBodies/UserCreateReq"
security: []
responses:
"201":
$ref: "#/components/responses/UserCreateRes"
@@ -74,13 +75,16 @@ paths:
parameters:
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Order"
- $ref: "#/components/parameters/Direction"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/Status"
- $ref: "#/components/parameters/FirstName"
- $ref: "#/components/parameters/LastName"
- $ref: "#/components/parameters/Username"
- $ref: "#/components/parameters/Email"
- $ref: "#/components/parameters/Tags"
- $ref: "#/components/parameters/Tag"
- $ref: "#/components/parameters/OnlyTotal"
security:
- bearerAuth: []
responses:
@@ -139,6 +143,8 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity."
"404":
description: A non-existent entity request.
"422":
@@ -197,6 +203,8 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity."
"404":
description: A non-existent entity request.
"405":
@@ -550,155 +558,6 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/groups/{groupID}/users:
get:
operationId: listUsersInGroup
tags:
- Users
summary: List users in a group
description: |
Retrieves a list of users in a group. 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: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/GroupID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Level"
- $ref: "#/components/parameters/Tree"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/GroupName"
- $ref: "#/components/parameters/ParentID"
responses:
"200":
$ref: "#/components/responses/MembersPageRes"
"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"
/{domainID}/channels/{channelID}/users:
get:
operationId: listUsersInChannel
tags:
- Users
summary: List users in a channel
description: |
Retrieves a list of users in a channel. 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: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/ChannelID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Level"
- $ref: "#/components/parameters/Tree"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/ChannelName"
- $ref: "#/components/parameters/ParentID"
responses:
"200":
$ref: "#/components/responses/MembersPageRes"
"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"
/{domainID}/clients/{clientID}/users:
get:
operationId: listUsersInClient
tags:
- Users
summary: List users associated with a client
description: |
Retrieves a list of users associated with a client. 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: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/ClientID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Level"
- $ref: "#/components/parameters/Tree"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/ChannelName"
- $ref: "#/components/parameters/ParentID"
responses:
"200":
$ref: "#/components/responses/MembersPageRes"
"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"
/{domainID}/users:
get:
summary: List users assigned to domain
description: |
List users assigned to domain that is identified by the domain ID.
tags:
- Users
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/Status"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/UserPageRes"
description: List of users 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.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/users/tokens/issue:
post:
operationId: issueToken
@@ -751,6 +610,54 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/users/send-verification:
post:
operationId: sendVerification
tags:
- Users
summary: Sends a verification email
description: |
Sends a verification email to the user.
security:
- bearerAuth: []
responses:
"200":
description: Sent verification email if registered.
"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"
/verify-email:
get:
operationId: verifyEmail
tags:
- Users
summary: Verify user's email
description: |
Verify user's email using the token from the verification link.
parameters:
- $ref: "#/components/parameters/VerificationToken"
responses:
"200":
description: Email verified successfully.
"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"
/health:
get:
operationId: health
@@ -779,7 +686,7 @@ components:
description: User's last name.
email:
type: string
example: "admin@example.com"
example: "user@example.com"
description: User's email address will be used as its unique identifier.
tags:
type: array
@@ -793,14 +700,17 @@ components:
properties:
username:
type: string
example: "admin"
description: User's username for example 'admin' will be used as its unique identifier.
example: "userName"
description: User's username for example 'userName' will be used as its unique identifier.
secret:
type: string
format: password
example: password
minimum: 8
description: Free-form account secret used for acquiring auth token(s).
required:
- username
- secret
metadata:
type: object
example: { "domain": "example.com" }
@@ -814,8 +724,14 @@ components:
description: User Status
format: string
example: enabled
enum:
- enabled
- disabled
required:
- credentials
- first_name
- last_name
- email
User:
type: object
@@ -953,6 +869,7 @@ components:
description: Total number of items.
offset:
type: integer
example: 1
description: Number of items to skip during retrieval.
limit:
type: integer
@@ -961,32 +878,7 @@ components:
required:
- users
- total
- offset
MembersPage:
type: object
properties:
members:
type: array
minItems: 0
uniqueItems: true
items:
$ref: "#/components/schemas/Members"
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:
- members
- total
- level
- limit
UserUpdate:
type: object
@@ -1130,18 +1022,18 @@ components:
IssueToken:
type: object
properties:
identity:
username:
type: string
example: user@supermq.com
description: User identity - email address.
secret:
example: myUsername
description: Users' username.
password:
type: string
example: password
minimum: 8
description: User secret password.
required:
- identity
- secret
- username
- password
Error:
type: object
@@ -1183,6 +1075,7 @@ components:
in: header
schema:
type: string
example: "example.com"
required: true
UserID:
@@ -1245,18 +1138,14 @@ components:
required: false
example: enabled
Tags:
name: tags
description: User tags.
Tag:
name: tag
description: User tag.
in: query
schema:
type: array
minItems: 0
uniqueItems: true
items:
type: string
type: string
required: false
example: ["yello", "orange"]
example: "orange"
GroupName:
name: name
@@ -1310,7 +1199,7 @@ components:
pattern: "^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$"
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
ClientID:
name: clientID
description: Unique client identifier.
@@ -1371,8 +1260,12 @@ components:
description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
in: query
schema:
type: string
minimum: 0
type: object
properties:
key:
type: string
description: Metadata key to filter by.
example: { "key": "value" }
required: false
Limit:
@@ -1398,6 +1291,44 @@ components:
required: false
example: "0"
Order:
name: order
description: Field by which to order the results
in: query
schema:
type: string
required: false
example: created_at
Direction:
name: dir
description: Direction of ordering the results.
in: query
schema:
type: string
enum:
- asc
- desc
required: false
example: desc
OnlyTotal:
name: only_total
description: If true, the response will contain only the total number of users that match the query parameters.
in: query
schema:
type: boolean
default: false
required: false
VerificationToken:
name: token
description: Verification token.
in: query
schema:
type: string
required: true
requestBodies:
UserCreateReq:
description: JSON-formatted document describing the new user to be registered
@@ -1498,11 +1429,8 @@ components:
email:
type: string
format: email
example: user@example.com
description: User email.
host:
type: string
example: examplehost
description: Email host.
PasswordReset:
description: Password reset request data, new password and token that is appended on password reset link received in email.
@@ -1515,13 +1443,13 @@ components:
type: string
format: password
description: New password.
example: 12345678
example: "12345678"
minimum: 8
confirm_password:
type: string
format: password
description: New confirmation password.
example: 12345678
example: "12345678"
minimum: 8
token:
type: string
@@ -1565,14 +1493,6 @@ components:
operationId: getUser
parameters:
userID: $response.body#/id
get_groups:
operationId: listUsersInGroup
parameters:
groupID: $response.body#/id
get_channels:
operationId: listUsersInChannel
parameters:
channelID: $response.body#/id
update:
operationId: updateUser
parameters:
@@ -1612,15 +1532,6 @@ components:
application/json:
schema:
$ref: "#/components/schemas/User"
links:
get_groups:
operationId: listUsersInGroup
parameters:
groupID: $response.body#/id
get_channels:
operationId: listUsersInChannel
parameters:
channelID: $response.body#/id
UserPageRes:
description: Data retrieved.
@@ -1629,13 +1540,6 @@ components:
schema:
$ref: "#/components/schemas/UsersPage"
MembersPageRes:
description: Group members retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/MembersPage"
TokenRes:
description: JSON-formated document describing the user access token used for authenticating into the syetem and refresh token used for generating another access token
content:
+328 -38
View File
@@ -40,7 +40,7 @@ The following actions are supported:
## Domains
Domains are used to group users and clients. Each domain has a unique alias that is used to identify the domain. Domains are used to group users and their entities.
Domains are used to group users and clients. Each domain has a unique route that is associated with the domain. Domains are used to group users and their entities.
Domain consists of the following fields:
@@ -48,7 +48,7 @@ Domain consists of the following fields:
- Name - name of the domain
- Tags - array of tags
- Metadata - Arbitrary, object-encoded domain's data
- Alias - unique alias of the domain
- Route - unique route of the domain used in messaging
- CreatedAt - timestamp at which the domain is created
- UpdatedAt - timestamp at which the domain is updated
- UpdatedBy - user that updated the domain
@@ -59,44 +59,54 @@ Domain consists of the following fields:
The service is configured using the environment variables presented in the following table. Note that any unset variables will be replaced with their default values.
| Variable | Description | Default |
| ------------------------------- | ----------------------------------------------------------------------- | ------------------------------ |
| SMQ_AUTH_LOG_LEVEL | Log level for the Auth service (debug, info, warn, error) | info |
| SMQ_AUTH_DB_HOST | Database host address | localhost |
| SMQ_AUTH_DB_PORT | Database host port | 5432 |
| SMQ_AUTH_DB_USER | Database user | supermq |
| SMQ_AUTH_DB_PASSWORD | Database password | supermq |
| SMQ_AUTH_DB_NAME | Name of the database used by the service | auth |
| SMQ_AUTH_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable |
| SMQ_AUTH_DB_SSL_CERT | Path to the PEM encoded certificate file | "" |
| SMQ_AUTH_DB_SSL_KEY | Path to the PEM encoded key file | "" |
| SMQ_AUTH_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | "" |
| SMQ_AUTH_HTTP_HOST | Auth service HTTP host | "" |
| SMQ_AUTH_HTTP_PORT | Auth service HTTP port | 8189 |
| SMQ_AUTH_HTTP_SERVER_CERT | Path to the PEM encoded HTTP server certificate file | "" |
| SMQ_AUTH_HTTP_SERVER_KEY | Path to the PEM encoded HTTP server key file | "" |
| SMQ_AUTH_GRPC_HOST | Auth service gRPC host | "" |
| SMQ_AUTH_GRPC_PORT | Auth service gRPC port | 8181 |
| SMQ_AUTH_GRPC_SERVER_CERT | Path to the PEM encoded gRPC server certificate file | "" |
| SMQ_AUTH_GRPC_SERVER_KEY | Path to the PEM encoded gRPC server key file | "" |
| SMQ_AUTH_GRPC_SERVER_CA_CERTS | Path to the PEM encoded gRPC server CA certificate file | "" |
| SMQ_AUTH_GRPC_CLIENT_CA_CERTS | Path to the PEM encoded gRPC client CA certificate file | "" |
| SMQ_AUTH_SECRET_KEY | String used for signing tokens | secret |
| SMQ_AUTH_ACCESS_TOKEN_DURATION | The access token expiration period | 1h |
| SMQ_AUTH_REFRESH_TOKEN_DURATION | The refresh token expiration period | 24h |
| SMQ_AUTH_INVITATION_DURATION | The invitation token expiration period | 168h |
| SMQ_SPICEDB_HOST | SpiceDB host address | localhost |
| SMQ_SPICEDB_PORT | SpiceDB host port | 50051 |
| SMQ_SPICEDB_PRE_SHARED_KEY | SpiceDB pre-shared key | 12345678 |
| SMQ_SPICEDB_SCHEMA_FILE | Path to SpiceDB schema file | ./docker/spicedb/schema.zed |
| SMQ_JAEGER_URL | Jaeger server URL | <http://jaeger:4318/v1/traces> |
| SMQ_JAEGER_TRACE_RATIO | Jaeger sampling ratio | 1.0 |
| SMQ_SEND_TELEMETRY | Send telemetry to supermq call home server | true |
| SMQ_AUTH_ADAPTER_INSTANCE_ID | Adapter instance ID | "" |
| Variable | Description | Default |
| ----------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------ |
| SMQ_AUTH_LOG_LEVEL | Log level for the Auth service (debug, info, warn, error) | info |
| SMQ_AUTH_DB_HOST | Database host address | localhost |
| SMQ_AUTH_DB_PORT | Database host port | 5432 |
| SMQ_AUTH_DB_USER | Database user | supermq |
| SMQ_AUTH_DB_PASSWORD | Database password | supermq |
| SMQ_AUTH_DB_NAME | Name of the database used by the service | auth |
| SMQ_AUTH_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable |
| SMQ_AUTH_DB_SSL_CERT | Path to the PEM encoded certificate file | "" |
| SMQ_AUTH_DB_SSL_KEY | Path to the PEM encoded key file | "" |
| SMQ_AUTH_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | "" |
| SMQ_AUTH_HTTP_HOST | Auth service HTTP host | "" |
| SMQ_AUTH_HTTP_PORT | Auth service HTTP port | 8189 |
| SMQ_AUTH_HTTP_SERVER_CERT | Path to the PEM encoded HTTP server certificate file | "" |
| SMQ_AUTH_HTTP_SERVER_KEY | Path to the PEM encoded HTTP server key file | "" |
| SMQ_AUTH_GRPC_HOST | Auth service gRPC host | "" |
| SMQ_AUTH_GRPC_PORT | Auth service gRPC port | 8181 |
| SMQ_AUTH_GRPC_SERVER_CERT | Path to the PEM encoded gRPC server certificate file | "" |
| SMQ_AUTH_GRPC_SERVER_KEY | Path to the PEM encoded gRPC server key file | "" |
| SMQ_AUTH_GRPC_SERVER_CA_CERTS | Path to the PEM encoded gRPC server CA certificate file | "" |
| SMQ_AUTH_GRPC_CLIENT_CA_CERTS | Path to the PEM encoded gRPC client CA certificate file | "" |
| SMQ_AUTH_SECRET_KEY | String used for signing tokens | secret |
| SMQ_AUTH_ACCESS_TOKEN_DURATION | The access token expiration period | 1h |
| SMQ_AUTH_REFRESH_TOKEN_DURATION | The refresh token expiration period | 24h |
| SMQ_AUTH_INVITATION_DURATION | The invitation token expiration period | 168h |
| SMQ_AUTH_CACHE_URL | Redis URL for caching PAT scopes | redis://localhost:6379/0 |
| SMQ_AUTH_CACHE_KEY_DURATION | Duration for which PAT scope cache keys are valid | 10m |
| SMQ_SPICEDB_HOST | SpiceDB host address | localhost |
| SMQ_SPICEDB_PORT | SpiceDB host port | 50051 |
| SMQ_SPICEDB_PRE_SHARED_KEY | SpiceDB pre-shared key | 12345678 |
| SMQ_SPICEDB_SCHEMA_FILE | Path to SpiceDB schema file | ./docker/spicedb/schema.zed |
| SMQ_JAEGER_URL | Jaeger server URL | <http://jaeger:4318/v1/traces> |
| SMQ_JAEGER_TRACE_RATIO | Jaeger sampling ratio | 1.0 |
| SMQ_SEND_TELEMETRY | Send telemetry to supermq call home server | true |
| SMQ_ADAPTER_INSTANCE_ID | Adapter instance ID | "" |
| SMQ_CALLOUT_URLS | Comma-separated list of callout URLs | "" |
| SMQ_CALLOUT_METHOD | Callout method | POST |
| SMQ_CALLOUT_TLS_VERIFICATION | Enable TLS verification for callouts | true |
| SMQ_CALLOUT_TIMEOUT | Callout timeout | 10s |
| SMQ_CALLOUT_CA_CERT | Path to CA certificate file | "" |
| SMQ_CALLOUT_CERT | Path to client certificate file | "" |
| SMQ_CALLOUT_KEY | Path to client key file | "" |
| SMQ_CALLOUT_OPERATIONS | Invoke callout if the authorization permission matches any of the given permissions. | "" |
## Deployment
The service itself is distributed as Docker container. Check the [`auth`](https://github.com/absmach/supermq/blob/main/docker/docker-compose.yml) service section in docker-compose file to see how service is deployed.
The service itself is distributed as Docker container. Check the [`auth`](https://github.com/absmach/supermq/blob/main/docker/docker-compose.yaml) 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:
@@ -146,14 +156,294 @@ SMQ_JAEGER_URL=http://localhost:14268/api/traces \
SMQ_JAEGER_TRACE_RATIO=1.0 \
SMQ_SEND_TELEMETRY=true \
SMQ_AUTH_ADAPTER_INSTANCE_ID="" \
SMQ_CALLOUT_URLS="" \
SMQ_CALLOUT_METHOD="POST" \
SMQ_CALLOUT_TLS_VERIFICATION=true \
$GOBIN/supermq-auth
```
Setting `SMQ_AUTH_HTTP_SERVER_CERT` and `SMQ_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 `SMQ_AUTH_GRPC_SERVER_CERT` and `SMQ_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 `SMQ_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 `SMQ_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.
## Personal Access Tokens (PATs)
Personal Access Tokens (PATs) provide a secure way to authenticate with SuperMQ APIs without using your primary credentials. They are particularly useful for automation, CI/CD pipelines, and integrating with third-party services.
### Overview
PATs in SuperMQ are designed with the following features:
- **Scoped Access**: Each token can be limited to specific operations on specific resources
- **Expiration Control**: Set custom expiration times for tokens
- **Revocable**: Tokens can be revoked at any time
- **Auditable**: Track when tokens were last used
- **Secure**: Tokens are stored as hashes, not in plaintext
### Token Structure
A PAT consists of three parts separated by underscores:
```
pat_<encoded-user-and-pat-id>_<random-string>
```
Where:
- `pat` is a fixed prefix
- `<encoded-user-and-pat-id>` is a base64-encoded combination of the user ID and PAT ID
- `<random-string>` is a randomly generated string for additional security
### PAT Operations
SuperMQ supports the following operations for PATs:
| Operation | Description |
| ----------- | ------------------------------------ |
| `create` | Create a new resource |
| `read` | Read/view a resource |
| `list` | List resources |
| `update` | Update/modify a resource |
| `delete` | Delete a resource |
| `share` | Share a resource with others |
| `unshare` | Remove sharing permissions |
| `publish` | Publish messages to a channel |
| `subscribe` | Subscribe to messages from a channel |
### Entity Types
PATs can be scoped to the following entity types:
| Entity Type | Description |
| ------------ | ---------------------- |
| `groups` | User groups |
| `channels` | Communication channels |
| `clients` | Client applications |
| `domains` | Organizational domains |
| `users` | User accounts |
| `dashboards` | Dashboard interfaces |
| `messages` | Message content |
### API Examples
#### Creating a PAT
```bash
curl --location 'http://localhost:9001/pats' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <access_token>' \
--data '{
"name": "test pat",
"description": "testing pat",
"duration": "24h"
}'
```
Response:
```json
{
"id": "a2500226-95dc-4285-87e2-e693e4a0a976",
"user_id": "user123",
"name": "pat 1",
"description": "for creating any client or channel",
"secret": "pat_dXNlcjEyM19hMjUwMDIyNi05NWRjLTQyODUtODdlMi1lNjkzZTRhMGE5NzY=_randomstring...",
"issued_at": "2025-02-27T11:20:59Z",
"expires_at": "2025-02-28T11:20:59Z"
}
```
#### Adding Scopes to a PAT
```bash
curl --location --request PATCH 'http://localhost:9001/pats/a2500226-95dc-4285-87e2-e693e4a0a976/scope/add' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <access_token>' \
--data '{
"scopes": [
{
"optional_domain_id": "c16c980a-9d4c-4793-8fb2-c81304cf1d9f",
"entity_type": "clients",
"operation": "create",
"entity_id": "*"
},
{
"optional_domain_id": "c16c980a-9d4c-4793-8fb2-c81304cf1d9f",
"entity_type": "channels",
"operation": "create",
"entity_id": "cfbc6936-5748-4339-a8ef-37b64b02bc96"
},
{
"entity_type": "dashboards",
"optional_domain_id": "c16c980a-9d4c-4793-8fb2-c81304cf1d9f",
"operation": "read",
"entity_id": "*"
}
]
}'
```
#### Listing PATs
```bash
curl --location 'http://localhost:9001/pats' \
--header 'Authorization: Bearer <access_token>'
```
#### Listing Scopes for a PAT
```bash
curl --location 'http://localhost:9001/pats/a2500226-95dc-4285-87e2-e693e4a0a976/scopes' \
--header 'Authorization: Bearer <access_token>'
```
#### Revoking a PAT
```bash
curl --location --request PATCH 'http://localhost:9001/pats/a2500226-95dc-4285-87e2-e693e4a0a976/revoke' \
--header 'Authorization: Bearer <access_token>'
```
#### Resetting a PAT Secret
```bash
curl --location --request PATCH 'http://localhost:9001/pats/a2500226-95dc-4285-87e2-e693e4a0a976/reset' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <access_token>' \
--data '{
"duration": "720h"
}'
```
### Using PATs for Authentication
When making API requests, include the PAT in the Authorization header:
```
Authorization: Bearer pat_<encoded-user-and-pat-id>_<random-string>
```
#### Example: Creating a Client Using PAT
```bash
curl --location 'http://localhost:9006/c16c980a-9d4c-4793-8fb2-c81304cf1d9f/clients' \
--header 'accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer pat_etKoiXKTR6a0zdgsBHC00qJQAiaV3EKFh+Lmk+SgqXY=_u7@5fyjgti9V@#Bw^bS*SPmX3OnH=HTvKwmIbxIuyBjoI|6FASo9egjKD^u-M$b|2Dpt3CXZtv&4k+hmYYjk&C$57AV59P%-iDV0' \
--data '{
"name": "test client",
"tags": [
"tag1",
"tag2"
],
"metadata":{"units":"km"},
"status": "enabled"
}'
```
This example shows how to create a client in a specific domain (`c16c980a-9d4c-4793-8fb2-c81304cf1d9f`) using a PAT for authentication. The PAT must have the appropriate scope (e.g., `clients` entity type with `create` operation) for this domain.
### Wildcard Entity IDs
When defining scopes for PATs, you can use the wildcard character `*` for the `entity_id` field to grant permissions for all entities of a specific type. This is particularly useful for automation tasks that need to operate on multiple resources.
For example:
- `"entity_id": "*"` - Grants permission for all entities of the specified type
- `"entity_id": "specific-id"` - Grants permission only for the entity with the specified ID
Using wildcards should be done carefully, as they grant broader permissions. Always follow the principle of least privilege by granting only the permissions necessary for the intended use case.
### Scope Examples
#### Allow Creating Any Client in a Domain
```json
{
"optional_domain_id": "domain_id",
"entity_type": "clients",
"operation": "create",
"entity_id": "*"
}
```
This scope allows the PAT to create any client within the specified domain. The wildcard `*` for `entity_id` means the token can create any client, not just a specific one.
#### Allow Publishing to a Specific Channel
```json
{
"optional_domain_id": "domain_id",
"entity_type": "channels",
"operation": "publish",
"entity_id": "channel_id"
}
```
This scope restricts the PAT to only publish to a specific channel (`channel_id`) within the specified domain. No wildcard is used, so the permission is limited to just this one channel.
#### Allow Reading All Dashboards
```json
{
"optional_domain_id": "domain_id",
"entity_type": "dashboards",
"operation": "read",
"entity_id": "*"
}
```
This scope allows the PAT to read all dashboards within the specified domain. The wildcard `*` for `entity_id` means the token can read any dashboard in that domain.
### Best Practices
1. **Limit Scope**: Always use the principle of least privilege when creating PATs
2. **Set Expirations**: Use reasonable expiration times for tokens
3. **Rotate Regularly**: Reset token secrets periodically
4. **Audit Usage**: Monitor when tokens are used
5. **Revoke Unused**: Remove tokens that are no longer needed
### Implementation Details
PATs are stored in the database with the following schema:
```sql
CREATE TABLE IF NOT EXISTS pats (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(254) NOT NULL,
user_id VARCHAR(36),
description TEXT,
secret TEXT,
issued_at TIMESTAMPTZ,
expires_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
revoked BOOLEAN,
revoked_at TIMESTAMPTZ,
last_used_at TIMESTAMPTZ,
UNIQUE (id, name, secret)
)
CREATE TABLE IF NOT EXISTS pat_scopes (
id VARCHAR(36) PRIMARY KEY,
pat_id VARCHAR(36) REFERENCES pats(id) ON DELETE CASCADE,
optional_domain_id VARCHAR(36),
entity_type VARCHAR(50) NOT NULL,
operation VARCHAR(50) NOT NULL,
entity_id VARCHAR(50) NOT NULL,
UNIQUE (pat_id, optional_domain_id, entity_type, operation, entity_id)
)
```
### Authorization
When a PAT is used for authentication:
1. The system parses the token to extract the user ID and PAT ID
2. It verifies the token hasn't been revoked or expired
3. It checks if the requested operation is allowed by the token's scopes
4. If all checks pass, the operation is authorized
## Usage
For more information about service capabilities and its usage, please check out the [API documentation](https://docs.api.supermq.abstractmachines.fr/?urls.primaryName=auth.yml).
For more information about service capabilities and its usage, please check out the [API documentation](https://docs.api.supermq.abstractmachines.fr/?urls.primaryName=auth.yaml).
[doc]: https://docs.supermq.abstractmachines.fr
+78 -10
View File
@@ -7,8 +7,9 @@ import (
"context"
"time"
grpcAuthV1 "github.com/absmach/supermq/api/grpc/auth/v1"
"github.com/absmach/supermq/auth"
grpcapi "github.com/absmach/supermq/auth/api/grpc"
grpcAuthV1 "github.com/absmach/supermq/internal/grpc/auth/v1"
"github.com/go-kit/kit/endpoint"
kitgrpc "github.com/go-kit/kit/transport/grpc"
"google.golang.org/grpc"
@@ -17,9 +18,11 @@ import (
const authSvcName = "auth.v1.AuthService"
type authGrpcClient struct {
authenticate endpoint.Endpoint
authorize endpoint.Endpoint
timeout time.Duration
authenticate endpoint.Endpoint
authenticatePAT endpoint.Endpoint
authorize endpoint.Endpoint
authorizePAT endpoint.Endpoint
timeout time.Duration
}
var _ grpcAuthV1.AuthServiceClient = (*authGrpcClient)(nil)
@@ -35,6 +38,14 @@ func NewAuthClient(conn *grpc.ClientConn, timeout time.Duration) grpcAuthV1.Auth
decodeIdentifyResponse,
grpcAuthV1.AuthNRes{},
).Endpoint(),
authenticatePAT: kitgrpc.NewClient(
conn,
authSvcName,
"AuthenticatePAT",
encodeIdentifyRequest,
decodeIdentifyPATResponse,
grpcAuthV1.AuthNRes{},
).Endpoint(),
authorize: kitgrpc.NewClient(
conn,
authSvcName,
@@ -43,6 +54,14 @@ func NewAuthClient(conn *grpc.ClientConn, timeout time.Duration) grpcAuthV1.Auth
decodeAuthorizeResponse,
grpcAuthV1.AuthZRes{},
).Endpoint(),
authorizePAT: kitgrpc.NewClient(
conn,
authSvcName,
"AuthorizePAT",
encodeAuthorizePATRequest,
decodeAuthorizeResponse,
grpcAuthV1.AuthZRes{},
).Endpoint(),
timeout: timeout,
}
}
@@ -56,17 +75,34 @@ func (client authGrpcClient) Authenticate(ctx context.Context, token *grpcAuthV1
return &grpcAuthV1.AuthNRes{}, grpcapi.DecodeError(err)
}
ir := res.(authenticateRes)
return &grpcAuthV1.AuthNRes{Id: ir.id, UserId: ir.userID, DomainId: ir.domainID}, nil
return &grpcAuthV1.AuthNRes{Id: ir.id, UserId: ir.userID, UserRole: uint32(ir.userRole), Verified: ir.verified}, nil
}
func encodeIdentifyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
func encodeIdentifyRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(authenticateReq)
return &grpcAuthV1.AuthNReq{Token: req.token}, nil
}
func decodeIdentifyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
func decodeIdentifyResponse(_ context.Context, grpcRes any) (any, error) {
res := grpcRes.(*grpcAuthV1.AuthNRes)
return authenticateRes{id: res.GetId(), userID: res.GetUserId(), domainID: res.GetDomainId()}, nil
return authenticateRes{id: res.GetId(), userID: res.GetUserId(), userRole: auth.Role(res.UserRole), verified: res.GetVerified()}, nil
}
func (client authGrpcClient) AuthenticatePAT(ctx context.Context, token *grpcAuthV1.AuthNReq, _ ...grpc.CallOption) (*grpcAuthV1.AuthNRes, error) {
ctx, cancel := context.WithTimeout(ctx, client.timeout)
defer cancel()
res, err := client.authenticatePAT(ctx, authenticateReq{token: token.GetToken()})
if err != nil {
return &grpcAuthV1.AuthNRes{}, grpcapi.DecodeError(err)
}
ir := res.(authenticateRes)
return &grpcAuthV1.AuthNRes{Id: ir.id, UserId: ir.userID, UserRole: uint32(ir.userRole)}, nil
}
func decodeIdentifyPATResponse(_ context.Context, grpcRes any) (any, error) {
res := grpcRes.(*grpcAuthV1.AuthNRes)
return authenticateRes{id: res.GetId(), userID: res.GetUserId(), userRole: auth.Role(res.UserRole)}, nil
}
func (client authGrpcClient) Authorize(ctx context.Context, req *grpcAuthV1.AuthZReq, _ ...grpc.CallOption) (r *grpcAuthV1.AuthZRes, err error) {
@@ -91,12 +127,12 @@ func (client authGrpcClient) Authorize(ctx context.Context, req *grpcAuthV1.Auth
return &grpcAuthV1.AuthZRes{Authorized: ar.authorized, Id: ar.id}, nil
}
func decodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
func decodeAuthorizeResponse(_ context.Context, grpcRes any) (any, error) {
res := grpcRes.(*grpcAuthV1.AuthZRes)
return authorizeRes{authorized: res.Authorized, id: res.Id}, nil
}
func encodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
func encodeAuthorizeRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(authReq)
return &grpcAuthV1.AuthZReq{
Domain: req.Domain,
@@ -109,3 +145,35 @@ func encodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}
Object: req.Object,
}, nil
}
func (client authGrpcClient) AuthorizePAT(ctx context.Context, req *grpcAuthV1.AuthZPatReq, _ ...grpc.CallOption) (r *grpcAuthV1.AuthZRes, err error) {
ctx, cancel := context.WithTimeout(ctx, client.timeout)
defer cancel()
res, err := client.authorizePAT(ctx, authPATReq{
userID: req.GetUserId(),
patID: req.GetPatId(),
entityType: auth.EntityType(req.GetEntityType()),
optionalDomainID: req.GetOptionalDomainId(),
operation: auth.Operation(req.GetOperation()),
entityID: req.GetEntityId(),
})
if err != nil {
return &grpcAuthV1.AuthZRes{}, grpcapi.DecodeError(err)
}
ar := res.(authorizeRes)
return &grpcAuthV1.AuthZRes{Authorized: ar.authorized, Id: ar.id}, nil
}
func encodeAuthorizePATRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(authPATReq)
return &grpcAuthV1.AuthZPatReq{
UserId: req.userID,
PatId: req.patID,
EntityType: uint32(req.entityType),
OptionalDomainId: req.optionalDomainID,
Operation: uint32(req.operation),
EntityId: req.entityID,
}, nil
}
+34 -3
View File
@@ -12,7 +12,7 @@ import (
)
func authenticateEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
return func(ctx context.Context, request any) (any, error) {
req := request.(authenticateReq)
if err := req.validate(); err != nil {
return authenticateRes{}, err
@@ -23,12 +23,28 @@ func authenticateEndpoint(svc auth.Service) endpoint.Endpoint {
return authenticateRes{}, err
}
return authenticateRes{id: key.Subject, userID: key.User, domainID: key.Domain}, nil
return authenticateRes{userID: key.Subject, userRole: key.Role, verified: key.Verified}, nil
}
}
func authenticatePATEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(authenticateReq)
if err := req.validate(); err != nil {
return authenticateRes{}, err
}
pat, err := svc.IdentifyPAT(ctx, req.token)
if err != nil {
return authenticateRes{}, err
}
return authenticateRes{id: pat.ID, userID: pat.User, userRole: pat.Role}, nil
}
}
func authorizeEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
return func(ctx context.Context, request any) (any, error) {
req := request.(authReq)
if err := req.validate(); err != nil {
@@ -50,3 +66,18 @@ func authorizeEndpoint(svc auth.Service) endpoint.Endpoint {
return authorizeRes{authorized: true}, nil
}
}
func authorizePATEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(authPATReq)
if err := req.validate(); err != nil {
return authorizeRes{}, err
}
err := svc.AuthorizePAT(ctx, req.userID, req.patID, req.entityType, req.optionalDomainID, req.operation, req.entityID)
if err != nil {
return authorizeRes{authorized: false}, err
}
return authorizeRes{authorized: true}, nil
}
}
+170 -26
View File
@@ -10,11 +10,11 @@ import (
"testing"
"time"
grpcAuthV1 "github.com/absmach/supermq/api/grpc/auth/v1"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
grpcapi "github.com/absmach/supermq/auth/api/grpc/auth"
grpcAuthV1 "github.com/absmach/supermq/internal/grpc/auth/v1"
"github.com/absmach/supermq/internal/testsutil"
"github.com/absmach/supermq/pkg/apiutil"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/stretchr/testify/assert"
@@ -32,7 +32,7 @@ const (
usersType = "users"
description = "Description"
groupName = "smqx"
adminpermission = "admin"
adminPermission = "admin"
authoritiesObj = "authorities"
memberRelation = "member"
@@ -41,12 +41,15 @@ const (
invalidDuration = 7 * 24 * time.Hour
validToken = "valid"
inValidToken = "invalid"
validPATToken = "valid"
inValidPATToken = "invalid"
validPolicy = "valid"
)
var (
domainID = testsutil.GenerateUUID(&testing.T{})
authAddr = fmt.Sprintf("localhost:%d", port)
clientID = testsutil.GenerateUUID(&testing.T{})
)
func startGRPCServer(svc auth.Service, port int) *grpc.Server {
@@ -63,8 +66,8 @@ func startGRPCServer(svc auth.Service, port int) *grpc.Server {
func TestIdentify(t *testing.T) {
conn, err := grpc.NewClient(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
defer conn.Close()
assert.Nil(t, err, fmt.Sprintf("Unexpected error creating client connection %s", err))
defer conn.Close()
grpcClient := grpcapi.NewAuthClient(conn, time.Second)
cases := []struct {
@@ -77,7 +80,7 @@ func TestIdentify(t *testing.T) {
{
desc: "authenticate user with valid user token",
token: validToken,
idt: &grpcAuthV1.AuthNRes{Id: id, UserId: email, DomainId: domainID},
idt: &grpcAuthV1.AuthNRes{UserId: id, UserRole: uint32(auth.UserRole)},
err: nil,
},
{
@@ -96,20 +99,23 @@ func TestIdentify(t *testing.T) {
}
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(), &grpcAuthV1.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()
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("Identify", mock.Anything, mock.Anything).Return(auth.Key{Subject: id, Role: auth.UserRole}, tc.svcErr)
idt, err := grpcClient.Authenticate(context.Background(), &grpcAuthV1.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()))
defer conn.Close()
assert.Nil(t, err, fmt.Sprintf("Unexpected error creating client connection %s", err))
defer conn.Close()
grpcClient := grpcapi.NewAuthClient(conn, time.Second)
cases := []struct {
@@ -128,7 +134,7 @@ func TestAuthorize(t *testing.T) {
Object: authoritiesObj,
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
Permission: adminPermission,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: true},
err: nil,
@@ -142,7 +148,7 @@ func TestAuthorize(t *testing.T) {
Object: authoritiesObj,
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
Permission: adminPermission,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: false},
err: svcerr.ErrAuthorization,
@@ -156,7 +162,7 @@ func TestAuthorize(t *testing.T) {
Object: authoritiesObj,
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
Permission: adminPermission,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: false},
err: apiutil.ErrMissingPolicySub,
@@ -170,7 +176,7 @@ func TestAuthorize(t *testing.T) {
Object: authoritiesObj,
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
Permission: adminPermission,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: false},
err: apiutil.ErrMissingPolicySub,
@@ -184,7 +190,7 @@ func TestAuthorize(t *testing.T) {
Object: "",
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
Permission: adminPermission,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: false},
err: apiutil.ErrMissingPolicyObj,
@@ -198,7 +204,7 @@ func TestAuthorize(t *testing.T) {
Object: authoritiesObj,
ObjectType: "",
Relation: memberRelation,
Permission: adminpermission,
Permission: adminPermission,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: false},
err: apiutil.ErrMissingPolicyObj,
@@ -219,12 +225,150 @@ func TestAuthorize(t *testing.T) {
},
}
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()
t.Run(tc.desc, func(t *testing.T) {
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()
})
}
}
func TestIdentifyPAT(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))
defer conn.Close()
grpcClient := grpcapi.NewAuthClient(conn, time.Second)
cases := []struct {
desc string
token string
idt *grpcAuthV1.AuthNRes
svcErr error
err error
}{
{
desc: "authenticate user with valid user token",
token: validToken,
idt: &grpcAuthV1.AuthNRes{Id: id, UserId: clientID},
err: nil,
},
{
desc: "authenticate user with invalid user token",
token: "invalid",
idt: &grpcAuthV1.AuthNRes{},
svcErr: svcerr.ErrAuthentication,
err: svcerr.ErrAuthentication,
},
{
desc: "authenticate user with empty token",
token: "",
idt: &grpcAuthV1.AuthNRes{},
err: apiutil.ErrBearerToken,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("IdentifyPAT", mock.Anything, tc.token).Return(auth.PAT{ID: id, User: clientID, IssuedAt: time.Now()}, tc.svcErr)
idt, err := grpcClient.AuthenticatePAT(context.Background(), &grpcAuthV1.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 TestAuthorizePAT(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))
defer conn.Close()
grpcClient := grpcapi.NewAuthClient(conn, time.Second)
cases := []struct {
desc string
token string
authRequest *grpcAuthV1.AuthZPatReq
authResponse *grpcAuthV1.AuthZRes
err error
}{
{
desc: "authorize user with authorized token",
token: validPATToken,
authRequest: &grpcAuthV1.AuthZPatReq{
UserId: id,
PatId: id,
EntityType: uint32(auth.ClientsType),
OptionalDomainId: domainID,
Operation: uint32(auth.CreateOp),
EntityId: clientID,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: true},
err: nil,
},
{
desc: "authorize user with unauthorized token",
token: inValidPATToken,
authRequest: &grpcAuthV1.AuthZPatReq{
UserId: id,
PatId: id,
EntityType: uint32(auth.ClientsType),
OptionalDomainId: domainID,
Operation: uint32(auth.CreateOp),
EntityId: clientID,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: false},
err: svcerr.ErrAuthorization,
},
{
desc: "authorize user with missing user id",
token: validPATToken,
authRequest: &grpcAuthV1.AuthZPatReq{
PatId: id,
EntityType: uint32(auth.ClientsType),
OptionalDomainId: domainID,
Operation: uint32(auth.CreateOp),
EntityId: clientID,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: false},
err: apiutil.ErrMissingUserID,
},
{
desc: "authorize user with missing pat id",
token: validPATToken,
authRequest: &grpcAuthV1.AuthZPatReq{
UserId: id,
EntityType: uint32(auth.ClientsType),
OptionalDomainId: domainID,
Operation: uint32(auth.CreateOp),
EntityId: clientID,
},
authResponse: &grpcAuthV1.AuthZRes{Authorized: false},
err: apiutil.ErrMissingPATID,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("AuthorizePAT",
mock.Anything,
tc.authRequest.UserId,
tc.authRequest.PatId,
mock.Anything,
tc.authRequest.OptionalDomainId,
mock.Anything,
mock.Anything,
mock.Anything).Return(tc.err)
ar, err := grpcClient.AuthorizePAT(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()
})
}
}
+21 -1
View File
@@ -4,7 +4,8 @@
package auth
import (
"github.com/absmach/supermq/pkg/apiutil"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
)
type authenticateReq struct {
@@ -49,3 +50,22 @@ func (req authReq) validate() error {
return nil
}
type authPATReq struct {
userID string
patID string
entityType auth.EntityType
optionalDomainID string
operation auth.Operation
entityID string
}
func (req authPATReq) validate() error {
if req.userID == "" {
return apiutil.ErrMissingUserID
}
if req.patID == "" {
return apiutil.ErrMissingPATID
}
return nil
}
+4 -1
View File
@@ -3,10 +3,13 @@
package auth
import smqauth "github.com/absmach/supermq/auth"
type authenticateRes struct {
id string
userID string
domainID string
userRole smqauth.Role
verified bool
}
type authorizeRes struct {
+55 -8
View File
@@ -6,9 +6,9 @@ package auth
import (
"context"
grpcAuthV1 "github.com/absmach/supermq/api/grpc/auth/v1"
"github.com/absmach/supermq/auth"
grpcapi "github.com/absmach/supermq/auth/api/grpc"
grpcAuthV1 "github.com/absmach/supermq/internal/grpc/auth/v1"
kitgrpc "github.com/go-kit/kit/transport/grpc"
)
@@ -16,8 +16,10 @@ var _ grpcAuthV1.AuthServiceServer = (*authGrpcServer)(nil)
type authGrpcServer struct {
grpcAuthV1.UnimplementedAuthServiceServer
authorize kitgrpc.Handler
authenticate kitgrpc.Handler
authorize kitgrpc.Handler
authenticate kitgrpc.Handler
authenticatePAT kitgrpc.Handler
authorizePAT kitgrpc.Handler
}
// NewAuthServer returns new AuthnServiceServer instance.
@@ -34,6 +36,18 @@ func NewAuthServer(svc auth.Service) grpcAuthV1.AuthServiceServer {
decodeAuthenticateRequest,
encodeAuthenticateResponse,
),
authenticatePAT: kitgrpc.NewServer(
(authenticatePATEndpoint(svc)),
decodeAuthenticateRequest,
encodeAuthenticatePATResponse,
),
authorizePAT: kitgrpc.NewServer(
(authorizePATEndpoint(svc)),
decodeAuthorizePATRequest,
encodeAuthorizeResponse,
),
}
}
@@ -45,6 +59,14 @@ func (s *authGrpcServer) Authenticate(ctx context.Context, req *grpcAuthV1.AuthN
return res.(*grpcAuthV1.AuthNRes), nil
}
func (s *authGrpcServer) AuthenticatePAT(ctx context.Context, req *grpcAuthV1.AuthNReq) (*grpcAuthV1.AuthNRes, error) {
_, res, err := s.authenticatePAT.ServeGRPC(ctx, req)
if err != nil {
return nil, grpcapi.EncodeError(err)
}
return res.(*grpcAuthV1.AuthNRes), nil
}
func (s *authGrpcServer) Authorize(ctx context.Context, req *grpcAuthV1.AuthZReq) (*grpcAuthV1.AuthZRes, error) {
_, res, err := s.authorize.ServeGRPC(ctx, req)
if err != nil {
@@ -53,17 +75,22 @@ func (s *authGrpcServer) Authorize(ctx context.Context, req *grpcAuthV1.AuthZReq
return res.(*grpcAuthV1.AuthZRes), nil
}
func decodeAuthenticateRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
func decodeAuthenticateRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(*grpcAuthV1.AuthNReq)
return authenticateReq{token: req.GetToken()}, nil
}
func encodeAuthenticateResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
func encodeAuthenticateResponse(_ context.Context, grpcRes any) (any, error) {
res := grpcRes.(authenticateRes)
return &grpcAuthV1.AuthNRes{Id: res.id, UserId: res.userID, DomainId: res.domainID}, nil
return &grpcAuthV1.AuthNRes{Id: res.id, UserId: res.userID, UserRole: uint32(res.userRole), Verified: res.verified}, nil
}
func decodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
func encodeAuthenticatePATResponse(_ context.Context, grpcRes any) (any, error) {
res := grpcRes.(authenticateRes)
return &grpcAuthV1.AuthNRes{Id: res.id, UserId: res.userID, UserRole: uint32(res.userRole)}, nil
}
func decodeAuthorizeRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(*grpcAuthV1.AuthZReq)
return authReq{
Domain: req.GetDomain(),
@@ -77,7 +104,27 @@ func decodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}
}, nil
}
func encodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
func encodeAuthorizeResponse(_ context.Context, grpcRes any) (any, error) {
res := grpcRes.(authorizeRes)
return &grpcAuthV1.AuthZRes{Authorized: res.authorized, Id: res.id}, nil
}
func decodeAuthorizePATRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(*grpcAuthV1.AuthZPatReq)
return authPATReq{
userID: req.GetUserId(),
patID: req.GetPatId(),
entityType: auth.EntityType(req.GetEntityType()),
optionalDomainID: req.GetOptionalDomainId(),
operation: auth.Operation(req.GetOperation()),
entityID: req.GetEntityId(),
}, nil
}
func (s *authGrpcServer) AuthorizePAT(ctx context.Context, req *grpcAuthV1.AuthZPatReq) (*grpcAuthV1.AuthZRes, error) {
_, res, err := s.authorizePAT.ServeGRPC(ctx, req)
if err != nil {
return nil, grpcapi.EncodeError(err)
}
return res.(*grpcAuthV1.AuthZRes), nil
}
+15 -11
View File
@@ -7,9 +7,9 @@ import (
"context"
"time"
grpcTokenV1 "github.com/absmach/supermq/api/grpc/token/v1"
"github.com/absmach/supermq/auth"
grpcapi "github.com/absmach/supermq/auth/api/grpc"
grpcTokenV1 "github.com/absmach/supermq/internal/grpc/token/v1"
"github.com/go-kit/kit/endpoint"
kitgrpc "github.com/go-kit/kit/transport/grpc"
"google.golang.org/grpc"
@@ -53,8 +53,10 @@ func (client tokenGrpcClient) Issue(ctx context.Context, req *grpcTokenV1.IssueR
defer cancel()
res, err := client.issue(ctx, issueReq{
userID: req.GetUserId(),
keyType: auth.KeyType(req.GetType()),
userID: req.GetUserId(),
userRole: auth.Role(req.GetUserRole()),
keyType: auth.KeyType(req.GetType()),
verified: req.GetVerified(),
})
if err != nil {
return &grpcTokenV1.Token{}, grpcapi.DecodeError(err)
@@ -62,15 +64,17 @@ func (client tokenGrpcClient) Issue(ctx context.Context, req *grpcTokenV1.IssueR
return res.(*grpcTokenV1.Token), nil
}
func encodeIssueRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
func encodeIssueRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(issueReq)
return &grpcTokenV1.IssueReq{
UserId: req.userID,
Type: uint32(req.keyType),
UserId: req.userID,
UserRole: uint32(req.userRole),
Type: uint32(req.keyType),
Verified: req.verified,
}, nil
}
func decodeIssueResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
func decodeIssueResponse(_ context.Context, grpcRes any) (any, error) {
return grpcRes, nil
}
@@ -78,18 +82,18 @@ func (client tokenGrpcClient) Refresh(ctx context.Context, req *grpcTokenV1.Refr
ctx, cancel := context.WithTimeout(ctx, client.timeout)
defer cancel()
res, err := client.refresh(ctx, refreshReq{refreshToken: req.GetRefreshToken()})
res, err := client.refresh(ctx, refreshReq{refreshToken: req.GetRefreshToken(), verified: req.GetVerified()})
if err != nil {
return &grpcTokenV1.Token{}, grpcapi.DecodeError(err)
}
return res.(*grpcTokenV1.Token), nil
}
func encodeRefreshRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
func encodeRefreshRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(refreshReq)
return &grpcTokenV1.RefreshReq{RefreshToken: req.refreshToken}, nil
return &grpcTokenV1.RefreshReq{RefreshToken: req.refreshToken, Verified: req.verified}, nil
}
func decodeRefreshResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
func decodeRefreshResponse(_ context.Context, grpcRes any) (any, error) {
return grpcRes, nil
}
+7 -5
View File
@@ -11,15 +11,17 @@ import (
)
func issueEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
return func(ctx context.Context, request any) (any, error) {
req := request.(issueReq)
if err := req.validate(); err != nil {
return issueRes{}, err
}
key := auth.Key{
Type: req.keyType,
User: req.userID,
Type: req.keyType,
Subject: req.userID,
Role: req.userRole,
Verified: req.verified,
}
tkn, err := svc.Issue(ctx, "", key)
if err != nil {
@@ -35,13 +37,13 @@ func issueEndpoint(svc auth.Service) endpoint.Endpoint {
}
func refreshEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
return func(ctx context.Context, request any) (any, error) {
req := request.(refreshReq)
if err := req.validate(); err != nil {
return issueRes{}, err
}
key := auth.Key{Type: auth.RefreshKey}
key := auth.Key{Type: auth.RefreshKey, Verified: req.verified}
tkn, err := svc.Issue(ctx, req.refreshToken, key)
if err != nil {
return issueRes{}, err
+3 -3
View File
@@ -10,11 +10,11 @@ import (
"testing"
"time"
grpcTokenV1 "github.com/absmach/supermq/api/grpc/token/v1"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
grpcapi "github.com/absmach/supermq/auth/api/grpc/token"
grpcTokenV1 "github.com/absmach/supermq/internal/grpc/token/v1"
"github.com/absmach/supermq/internal/testsutil"
"github.com/absmach/supermq/pkg/apiutil"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/stretchr/testify/assert"
@@ -32,7 +32,7 @@ const (
usersType = "users"
description = "Description"
groupName = "smqx"
adminpermission = "admin"
adminPermission = "admin"
authoritiesObj = "authorities"
memberRelation = "member"
+6 -3
View File
@@ -4,13 +4,15 @@
package token
import (
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/apiutil"
)
type issueReq struct {
userID string
keyType auth.KeyType
userID string
userRole auth.Role
keyType auth.KeyType
verified bool
}
func (req issueReq) validate() error {
@@ -26,6 +28,7 @@ func (req issueReq) validate() error {
type refreshReq struct {
refreshToken string
verified bool
}
func (req refreshReq) validate() error {
+9 -7
View File
@@ -6,9 +6,9 @@ package token
import (
"context"
grpcTokenV1 "github.com/absmach/supermq/api/grpc/token/v1"
"github.com/absmach/supermq/auth"
grpcapi "github.com/absmach/supermq/auth/api/grpc"
grpcTokenV1 "github.com/absmach/supermq/internal/grpc/token/v1"
kitgrpc "github.com/go-kit/kit/transport/grpc"
)
@@ -52,20 +52,22 @@ func (s *tokenGrpcServer) Refresh(ctx context.Context, req *grpcTokenV1.RefreshR
return res.(*grpcTokenV1.Token), nil
}
func decodeIssueRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
func decodeIssueRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(*grpcTokenV1.IssueReq)
return issueReq{
userID: req.GetUserId(),
keyType: auth.KeyType(req.GetType()),
userID: req.GetUserId(),
userRole: auth.Role(req.GetUserRole()),
keyType: auth.KeyType(req.GetType()),
verified: req.Verified,
}, nil
}
func decodeRefreshRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
func decodeRefreshRequest(_ context.Context, grpcReq any) (any, error) {
req := grpcReq.(*grpcTokenV1.RefreshReq)
return refreshReq{refreshToken: req.GetRefreshToken()}, nil
return refreshReq{refreshToken: req.GetRefreshToken(), verified: req.Verified}, nil
}
func encodeIssueResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
func encodeIssueResponse(_ context.Context, grpcRes any) (any, error) {
res := grpcRes.(issueRes)
return &grpcTokenV1.Token{
+4 -2
View File
@@ -6,8 +6,8 @@ package grpc
import (
"fmt"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/apiutil"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"google.golang.org/grpc/codes"
@@ -25,7 +25,9 @@ func EncodeError(err error) error {
err == apiutil.ErrMissingMemberType,
err == apiutil.ErrMissingPolicySub,
err == apiutil.ErrMissingPolicyObj,
err == apiutil.ErrMalformedPolicyAct:
err == apiutil.ErrMalformedPolicyAct,
err == apiutil.ErrMissingUserID,
err == apiutil.ErrMissingPATID:
return status.Error(codes.InvalidArgument, err.Error())
case errors.Contains(err, svcerr.ErrAuthentication),
errors.Contains(err, auth.ErrKeyExpired),
+3 -3
View File
@@ -12,7 +12,7 @@ import (
)
func issueEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
return func(ctx context.Context, request any) (any, error) {
req := request.(issueKeyReq)
if err := req.validate(); err != nil {
return nil, err
@@ -44,7 +44,7 @@ func issueEndpoint(svc auth.Service) endpoint.Endpoint {
}
func retrieveEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
return func(ctx context.Context, request any) (any, error) {
req := request.(keyReq)
if err := req.validate(); err != nil {
@@ -71,7 +71,7 @@ func retrieveEndpoint(svc auth.Service) endpoint.Endpoint {
}
func revokeEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
return func(ctx context.Context, request any) (any, error) {
req := request.(keyReq)
if err := req.validate(); err != nil {
+40 -22
View File
@@ -14,12 +14,12 @@ import (
"testing"
"time"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
httpapi "github.com/absmach/supermq/auth/api/http"
"github.com/absmach/supermq/auth/jwt"
"github.com/absmach/supermq/auth/mocks"
smqlog "github.com/absmach/supermq/logger"
"github.com/absmach/supermq/pkg/apiutil"
svcerr "github.com/absmach/supermq/pkg/errors/service"
policymocks "github.com/absmach/supermq/pkg/policies/mocks"
"github.com/absmach/supermq/pkg/uuid"
@@ -37,6 +37,11 @@ const (
invalidDuration = 7 * 24 * time.Hour
)
var (
krepo *mocks.KeyRepository
pEvaluator *policymocks.Evaluator
)
type issueRequest struct {
Duration time.Duration `json:"duration,omitempty"`
Type uint32 `json:"type,omitempty"`
@@ -67,14 +72,17 @@ func (tr testRequest) make() (*http.Response, error) {
return tr.client.Do(req)
}
func newService() (auth.Service, *mocks.KeyRepository) {
krepo := new(mocks.KeyRepository)
func newService() auth.Service {
krepo = new(mocks.KeyRepository)
pRepo := new(mocks.PATSRepository)
cache := new(mocks.Cache)
hash := new(mocks.Hasher)
idProvider := uuid.NewMock()
pService := new(policymocks.Service)
pEvaluator := new(policymocks.Evaluator)
pEvaluator = new(policymocks.Evaluator)
t := jwt.New([]byte(secret))
return auth.New(krepo, idProvider, t, pEvaluator, pService, loginDuration, refreshDuration, invalidDuration), krepo
return auth.New(krepo, pRepo, cache, hash, idProvider, t, pEvaluator, pService, loginDuration, refreshDuration, invalidDuration)
}
func newServer(svc auth.Service) *httptest.Server {
@@ -82,7 +90,7 @@ func newServer(svc auth.Service) *httptest.Server {
return httptest.NewServer(mux)
}
func toJSON(data interface{}) string {
func toJSON(data any) string {
jsonData, err := json.Marshal(data)
if err != nil {
return ""
@@ -91,9 +99,11 @@ func toJSON(data interface{}) string {
}
func TestIssue(t *testing.T) {
svc, krepo := newService()
token, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.AccessKey, IssuedAt: time.Now(), Subject: id})
svc := newService()
policyCall := pEvaluator.On("CheckPolicy", mock.Anything, mock.Anything).Return(nil)
token, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.AccessKey, Role: auth.UserRole, IssuedAt: time.Now(), Subject: id})
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
policyCall.Unset()
ts := newServer(svc)
defer ts.Close()
@@ -191,24 +201,28 @@ func TestIssue(t *testing.T) {
token: tc.token,
body: strings.NewReader(tc.req),
}
repocall := krepo.On("Save", mock.Anything, mock.Anything).Return("", nil)
repoCall := krepo.On("Save", mock.Anything, mock.Anything).Return("", nil)
policyCall := pEvaluator.On("CheckPolicy", mock.Anything, mock.Anything).Return(nil)
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
repocall.Unset()
repoCall.Unset()
policyCall.Unset()
}
}
func TestRetrieve(t *testing.T) {
svc, krepo := newService()
token, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.AccessKey, IssuedAt: time.Now(), Subject: id})
svc := newService()
policyCall := pEvaluator.On("CheckPolicy", mock.Anything, mock.Anything).Return(nil)
token, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.AccessKey, Role: auth.UserRole, IssuedAt: time.Now(), Subject: id})
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
key := auth.Key{Type: auth.APIKey, IssuedAt: time.Now(), Subject: id}
repocall := krepo.On("Save", mock.Anything, mock.Anything).Return(mock.Anything, nil)
repoCall := krepo.On("Save", mock.Anything, mock.Anything).Return(mock.Anything, nil)
k, err := svc.Issue(context.Background(), token.AccessToken, key)
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
repocall.Unset()
repoCall.Unset()
policyCall.Unset()
ts := newServer(svc)
defer ts.Close()
@@ -265,24 +279,28 @@ func TestRetrieve(t *testing.T) {
url: fmt.Sprintf("%s/keys/%s", ts.URL, tc.id),
token: tc.token,
}
repocall := krepo.On("Retrieve", mock.Anything, mock.Anything, mock.Anything).Return(tc.key, tc.err)
policyCall := pEvaluator.On("CheckPolicy", mock.Anything, mock.Anything).Return(nil)
repoCall := krepo.On("Retrieve", mock.Anything, mock.Anything, mock.Anything).Return(tc.key, tc.err)
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
repocall.Unset()
repoCall.Unset()
policyCall.Unset()
}
}
func TestRevoke(t *testing.T) {
svc, krepo := newService()
token, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.AccessKey, IssuedAt: time.Now(), Subject: id})
svc := newService()
policyCall := pEvaluator.On("CheckPolicy", mock.Anything, mock.Anything).Return(nil)
token, err := svc.Issue(context.Background(), "", auth.Key{Type: auth.AccessKey, Role: auth.UserRole, IssuedAt: time.Now(), Subject: id})
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
key := auth.Key{Type: auth.APIKey, IssuedAt: time.Now(), Subject: id}
repocall := krepo.On("Save", mock.Anything, mock.Anything).Return(mock.Anything, nil)
repoCall := krepo.On("Save", mock.Anything, mock.Anything).Return(mock.Anything, nil)
k, err := svc.Issue(context.Background(), token.AccessToken, key)
assert.Nil(t, err, fmt.Sprintf("Issuing login key expected to succeed: %s", err))
repocall.Unset()
repoCall.Unset()
policyCall.Unset()
ts := newServer(svc)
defer ts.Close()
@@ -327,10 +345,10 @@ func TestRevoke(t *testing.T) {
url: fmt.Sprintf("%s/keys/%s", ts.URL, tc.id),
token: tc.token,
}
repocall := krepo.On("Remove", mock.Anything, mock.Anything, mock.Anything).Return(nil)
repoCall := krepo.On("Remove", mock.Anything, mock.Anything, mock.Anything).Return(nil)
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
repocall.Unset()
repoCall.Unset()
}
}
+1 -1
View File
@@ -6,8 +6,8 @@ package keys
import (
"time"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/apiutil"
)
type issueKeyReq struct {
+1 -1
View File
@@ -6,8 +6,8 @@ package keys
import (
"testing"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/apiutil"
"github.com/stretchr/testify/assert"
)
+4 -4
View File
@@ -10,9 +10,9 @@ import (
"net/http"
"strings"
api "github.com/absmach/supermq/api/http"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/internal/api"
"github.com/absmach/supermq/pkg/apiutil"
"github.com/absmach/supermq/pkg/errors"
"github.com/go-chi/chi/v5"
kithttp "github.com/go-kit/kit/transport/http"
@@ -50,7 +50,7 @@ func MakeHandler(svc auth.Service, mux *chi.Mux, logger *slog.Logger) *chi.Mux {
return mux
}
func decodeIssue(_ context.Context, r *http.Request) (interface{}, error) {
func decodeIssue(_ context.Context, r *http.Request) (any, error) {
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
return nil, apiutil.ErrUnsupportedContentType
}
@@ -63,7 +63,7 @@ func decodeIssue(_ context.Context, r *http.Request) (interface{}, error) {
return req, nil
}
func decodeKeyReq(_ context.Context, r *http.Request) (interface{}, error) {
func decodeKeyReq(_ context.Context, r *http.Request) (any, error) {
req := keyReq{
token: apiutil.ExtractBearerToken(r),
id: chi.URLParam(r, "id"),
+225
View File
@@ -0,0 +1,225 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package pats
import (
"context"
"github.com/absmach/supermq/auth"
"github.com/go-kit/kit/endpoint"
)
func createPATEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(createPatReq)
if err := req.validate(); err != nil {
return nil, err
}
pat, err := svc.CreatePAT(ctx, req.token, req.Name, req.Description, req.Duration)
if err != nil {
return nil, err
}
return createPatRes{pat}, nil
}
}
func retrievePATEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(retrievePatReq)
if err := req.validate(); err != nil {
return nil, err
}
pat, err := svc.RetrievePAT(ctx, req.token, req.id)
if err != nil {
return nil, err
}
return retrievePatRes{pat}, nil
}
}
func updatePATNameEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(updatePatNameReq)
if err := req.validate(); err != nil {
return nil, err
}
pat, err := svc.UpdatePATName(ctx, req.token, req.id, req.Name)
if err != nil {
return nil, err
}
return updatePatNameRes{pat}, nil
}
}
func updatePATDescriptionEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(updatePatDescriptionReq)
if err := req.validate(); err != nil {
return nil, err
}
pat, err := svc.UpdatePATDescription(ctx, req.token, req.id, req.Description)
if err != nil {
return nil, err
}
return updatePatDescriptionRes{pat}, nil
}
}
func listPATSEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(listPatsReq)
if err := req.validate(); err != nil {
return nil, err
}
pm := auth.PATSPageMeta{
Limit: req.limit,
Offset: req.offset,
Name: req.name,
ID: req.id,
Status: req.status,
}
patsPage, err := svc.ListPATS(ctx, req.token, pm)
if err != nil {
return nil, err
}
return listPatsRes{patsPage}, nil
}
}
func deletePATEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(deletePatReq)
if err := req.validate(); err != nil {
return nil, err
}
if err := svc.DeletePAT(ctx, req.token, req.id); err != nil {
return nil, err
}
return deletePatRes{}, nil
}
}
func resetPATSecretEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(resetPatSecretReq)
if err := req.validate(); err != nil {
return nil, err
}
pat, err := svc.ResetPATSecret(ctx, req.token, req.id, req.Duration)
if err != nil {
return nil, err
}
return resetPatSecretRes{pat}, nil
}
}
func revokePATSecretEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(revokePatSecretReq)
if err := req.validate(); err != nil {
return nil, err
}
if err := svc.RevokePATSecret(ctx, req.token, req.id); err != nil {
return nil, err
}
return revokePatSecretRes{}, nil
}
}
func clearAllPATEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(clearAllPATReq)
if err := req.validate(); err != nil {
return nil, err
}
if err := svc.RemoveAllPAT(ctx, req.token); err != nil {
return nil, err
}
return clearAllRes{}, nil
}
}
func addScopeEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(addScopeReq)
if err := req.validate(); err != nil {
return nil, err
}
err := svc.AddScope(ctx, req.token, req.id, req.Scopes)
if err != nil {
return nil, err
}
return scopeRes{}, nil
}
}
func removeScopeEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(removeScopeReq)
if err := req.validate(); err != nil {
return nil, err
}
err := svc.RemoveScope(ctx, req.token, req.id, req.ScopesID...)
if err != nil {
return nil, err
}
return scopeRes{}, nil
}
}
func clearAllScopeEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(clearAllScopeReq)
if err := req.validate(); err != nil {
return nil, err
}
if err := svc.RemovePATAllScope(ctx, req.token, req.id); err != nil {
return nil, err
}
return clearAllRes{}, nil
}
}
func listScopesEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(listScopesReq)
if err := req.validate(); err != nil {
return nil, err
}
pm := auth.ScopesPageMeta{
Limit: req.limit,
Offset: req.offset,
PatID: req.patID,
}
scopesPage, err := svc.ListScopes(ctx, req.token, pm)
if err != nil {
return nil, err
}
return listScopeRes{scopesPage}, nil
}
}
+287
View File
@@ -0,0 +1,287 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package pats
import (
"encoding/json"
"strings"
"time"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/errors"
)
type createPatReq struct {
token string
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Duration time.Duration `json:"duration,omitempty"`
}
func (cpr *createPatReq) UnmarshalJSON(data []byte) error {
var temp struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Duration string `json:"duration,omitempty"`
}
if err := json.Unmarshal(data, &temp); err != nil {
return err
}
duration, err := time.ParseDuration(temp.Duration)
if err != nil {
return err
}
cpr.Name = temp.Name
cpr.Description = temp.Description
cpr.Duration = duration
return nil
}
func (req createPatReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if strings.TrimSpace(req.Name) == "" {
return apiutil.ErrMissingName
}
return nil
}
type retrievePatReq struct {
token string
id string
}
func (req retrievePatReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.id == "" {
return apiutil.ErrMissingPATID
}
return nil
}
type updatePatNameReq struct {
token string
id string
Name string `json:"name,omitempty"`
}
func (req updatePatNameReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.id == "" {
return apiutil.ErrMissingPATID
}
if strings.TrimSpace(req.Name) == "" {
return apiutil.ErrMissingName
}
return nil
}
type updatePatDescriptionReq struct {
token string
id string
Description string `json:"description,omitempty"`
}
func (req updatePatDescriptionReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.id == "" {
return apiutil.ErrMissingPATID
}
if strings.TrimSpace(req.Description) == "" {
return apiutil.ErrMissingDescription
}
return nil
}
type listPatsReq struct {
token string
offset uint64
limit uint64
name string
id string
status auth.Status
}
func (req listPatsReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
return nil
}
type deletePatReq struct {
token string
id string
}
func (req deletePatReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.id == "" {
return apiutil.ErrMissingPATID
}
return nil
}
type resetPatSecretReq struct {
token string
id string
Duration time.Duration `json:"duration,omitempty"`
}
func (rspr *resetPatSecretReq) UnmarshalJSON(data []byte) error {
var temp struct {
Duration string `json:"duration,omitempty"`
}
err := json.Unmarshal(data, &temp)
if err != nil {
return err
}
rspr.Duration, err = time.ParseDuration(temp.Duration)
if err != nil {
return err
}
return nil
}
func (req resetPatSecretReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.id == "" {
return apiutil.ErrMissingPATID
}
return nil
}
type revokePatSecretReq struct {
token string
id string
}
func (req revokePatSecretReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.id == "" {
return apiutil.ErrMissingPATID
}
return nil
}
type clearAllPATReq struct {
token string
}
func (req clearAllPATReq) validate() error {
if req.token == "" {
return apiutil.ErrBearerToken
}
return nil
}
type addScopeReq struct {
token string
id string
Scopes []auth.Scope `json:"scopes,omitempty"`
}
func (req *addScopeReq) UnmarshalJSON(data []byte) error {
type Alias addScopeReq
aux := &struct {
*Alias
}{
Alias: (*Alias)(req),
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
return nil
}
func (req addScopeReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.id == "" {
return apiutil.ErrMissingPATID
}
if len(req.Scopes) == 0 {
return apiutil.ErrValidation
}
for _, scope := range req.Scopes {
if err := scope.Validate(); err != nil {
return errors.Wrap(apiutil.ErrValidation, err)
}
}
return nil
}
type removeScopeReq struct {
token string
id string
ScopesID []string `json:"scopes_id,omitempty"`
}
func (req removeScopeReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.id == "" {
return apiutil.ErrMissingPATID
}
if len(req.ScopesID) == 0 {
return apiutil.ErrValidation
}
return nil
}
type clearAllScopeReq struct {
token string
id string
}
func (req clearAllScopeReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.id == "" {
return apiutil.ErrMissingPATID
}
return nil
}
type listScopesReq struct {
token string
offset uint64
limit uint64
patID string
}
func (req listScopesReq) validate() (err error) {
if req.token == "" {
return apiutil.ErrBearerToken
}
if req.patID == "" {
return apiutil.ErrMissingPATID
}
return nil
}
+191
View File
@@ -0,0 +1,191 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package pats
import (
"net/http"
"github.com/absmach/supermq"
"github.com/absmach/supermq/auth"
)
var (
_ supermq.Response = (*createPatRes)(nil)
_ supermq.Response = (*retrievePatRes)(nil)
_ supermq.Response = (*updatePatNameRes)(nil)
_ supermq.Response = (*updatePatDescriptionRes)(nil)
_ supermq.Response = (*deletePatRes)(nil)
_ supermq.Response = (*resetPatSecretRes)(nil)
_ supermq.Response = (*revokePatSecretRes)(nil)
_ supermq.Response = (*scopeRes)(nil)
_ supermq.Response = (*clearAllRes)(nil)
)
type createPatRes struct {
auth.PAT `json:",inline"`
}
func (res createPatRes) Code() int {
return http.StatusCreated
}
func (res createPatRes) Headers() map[string]string {
return map[string]string{}
}
func (res createPatRes) Empty() bool {
return false
}
type retrievePatRes struct {
auth.PAT `json:",inline"`
}
func (res retrievePatRes) Code() int {
return http.StatusOK
}
func (res retrievePatRes) Headers() map[string]string {
return map[string]string{}
}
func (res retrievePatRes) Empty() bool {
return false
}
type updatePatNameRes struct {
auth.PAT `json:",inline"`
}
func (res updatePatNameRes) Code() int {
return http.StatusAccepted
}
func (res updatePatNameRes) Headers() map[string]string {
return map[string]string{}
}
func (res updatePatNameRes) Empty() bool {
return false
}
type updatePatDescriptionRes struct {
auth.PAT `json:",inline"`
}
func (res updatePatDescriptionRes) Code() int {
return http.StatusAccepted
}
func (res updatePatDescriptionRes) Headers() map[string]string {
return map[string]string{}
}
func (res updatePatDescriptionRes) Empty() bool {
return false
}
type listPatsRes struct {
auth.PATSPage `json:",inline"`
}
func (res listPatsRes) Code() int {
return http.StatusOK
}
func (res listPatsRes) Headers() map[string]string {
return map[string]string{}
}
func (res listPatsRes) Empty() bool {
return false
}
type deletePatRes struct{}
func (res deletePatRes) Code() int {
return http.StatusNoContent
}
func (res deletePatRes) Headers() map[string]string {
return map[string]string{}
}
func (res deletePatRes) Empty() bool {
return true
}
type resetPatSecretRes struct {
auth.PAT `json:",inline"`
}
func (res resetPatSecretRes) Code() int {
return http.StatusOK
}
func (res resetPatSecretRes) Headers() map[string]string {
return map[string]string{}
}
func (res resetPatSecretRes) Empty() bool {
return false
}
type revokePatSecretRes struct{}
func (res revokePatSecretRes) Code() int {
return http.StatusNoContent
}
func (res revokePatSecretRes) Headers() map[string]string {
return map[string]string{}
}
func (res revokePatSecretRes) Empty() bool {
return true
}
type scopeRes struct{}
func (res scopeRes) Code() int {
return http.StatusOK
}
func (res scopeRes) Headers() map[string]string {
return map[string]string{}
}
func (res scopeRes) Empty() bool {
return true
}
type clearAllRes struct{}
func (res clearAllRes) Code() int {
return http.StatusOK
}
func (res clearAllRes) Headers() map[string]string {
return map[string]string{}
}
func (res clearAllRes) Empty() bool {
return true
}
type listScopeRes struct {
auth.ScopesPage `json:",inline"`
}
func (res listScopeRes) Code() int {
return http.StatusOK
}
func (res listScopeRes) Headers() map[string]string {
return map[string]string{}
}
func (res listScopeRes) Empty() bool {
return false
}
+366
View File
@@ -0,0 +1,366 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package pats
import (
"context"
"encoding/json"
"log/slog"
"net/http"
"strings"
api "github.com/absmach/supermq/api/http"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/errors"
"github.com/go-chi/chi/v5"
kithttp "github.com/go-kit/kit/transport/http"
)
const (
contentType = "application/json"
defInterval = "30d"
patPrefix = "pat_"
)
// MakeHandler returns a HTTP handler for API endpoints.
func MakeHandler(svc auth.Service, mux *chi.Mux, logger *slog.Logger) *chi.Mux {
opts := []kithttp.ServerOption{
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)),
}
mux.Route("/pats", func(r chi.Router) {
r.Post("/", kithttp.NewServer(
createPATEndpoint(svc),
decodeCreatePATRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Get("/", kithttp.NewServer(
listPATSEndpoint(svc),
decodeListPATSRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Delete("/", kithttp.NewServer(
clearAllPATEndpoint(svc),
decodeClearAllPATRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Route("/{id}", func(r chi.Router) {
r.Get("/", kithttp.NewServer(
retrievePATEndpoint(svc),
decodeRetrievePATRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Patch("/name", kithttp.NewServer(
updatePATNameEndpoint(svc),
decodeUpdatePATNameRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Patch("/description", kithttp.NewServer(
updatePATDescriptionEndpoint(svc),
decodeUpdatePATDescriptionRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Delete("/", kithttp.NewServer(
deletePATEndpoint(svc),
decodeDeletePATRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Route("/secret", func(r chi.Router) {
r.Patch("/reset", kithttp.NewServer(
resetPATSecretEndpoint(svc),
decodeResetPATSecretRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Patch("/revoke", kithttp.NewServer(
revokePATSecretEndpoint(svc),
decodeRevokePATSecretRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
})
r.Route("/scope", func(r chi.Router) {
r.Patch("/add", kithttp.NewServer(
addScopeEndpoint(svc),
decodeAddScopeRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Get("/", kithttp.NewServer(
listScopesEndpoint(svc),
decodeListScopeRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Patch("/remove", kithttp.NewServer(
removeScopeEndpoint(svc),
decodeRemoveScopeRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
r.Delete("/", kithttp.NewServer(
clearAllScopeEndpoint(svc),
decodeClearAllScopeRequest,
api.EncodeResponse,
opts...,
).ServeHTTP)
})
})
})
return mux
}
func decodeCreatePATRequest(_ context.Context, r *http.Request) (any, error) {
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
return nil, apiutil.ErrUnsupportedContentType
}
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
req := createPatReq{token: token}
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 decodeRetrievePATRequest(_ context.Context, r *http.Request) (any, error) {
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
req := retrievePatReq{
token: token,
id: chi.URLParam(r, "id"),
}
return req, nil
}
func decodeUpdatePATNameRequest(_ context.Context, r *http.Request) (any, error) {
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
return nil, apiutil.ErrUnsupportedContentType
}
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
req := updatePatNameReq{
token: token,
id: chi.URLParam(r, "id"),
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
}
return req, nil
}
func decodeUpdatePATDescriptionRequest(_ context.Context, r *http.Request) (any, error) {
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
return nil, apiutil.ErrUnsupportedContentType
}
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
req := updatePatDescriptionReq{
token: token,
id: chi.URLParam(r, "id"),
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
}
return req, nil
}
func decodeListPATSRequest(_ context.Context, r *http.Request) (any, error) {
l, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
o, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
n, err := apiutil.ReadStringQuery(r, api.NameKey, "")
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
i, err := apiutil.ReadStringQuery(r, api.IDOrder, "")
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
s, err := apiutil.ReadStringQuery(r, api.StatusKey, "")
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
patStatus, err := auth.ToStatus(s)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
req := listPatsReq{
token: token,
limit: l,
offset: o,
name: n,
id: i,
status: patStatus,
}
return req, nil
}
func decodeDeletePATRequest(_ context.Context, r *http.Request) (any, error) {
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
return deletePatReq{
token: token,
id: chi.URLParam(r, "id"),
}, nil
}
func decodeResetPATSecretRequest(_ context.Context, r *http.Request) (any, error) {
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
return nil, apiutil.ErrUnsupportedContentType
}
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
req := resetPatSecretReq{
token: token,
id: chi.URLParam(r, "id"),
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
}
return req, nil
}
func decodeRevokePATSecretRequest(_ context.Context, r *http.Request) (any, error) {
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
return revokePatSecretReq{
token: token,
id: chi.URLParam(r, "id"),
}, nil
}
func decodeClearAllPATRequest(_ context.Context, r *http.Request) (any, error) {
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
return clearAllPATReq{
token: token,
}, nil
}
func decodeAddScopeRequest(_ context.Context, r *http.Request) (any, error) {
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
return nil, apiutil.ErrUnsupportedContentType
}
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
req := addScopeReq{
token: token,
id: chi.URLParam(r, "id"),
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
}
return req, nil
}
func decodeListScopeRequest(_ context.Context, r *http.Request) (any, error) {
l, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
o, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset)
if err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
req := listScopesReq{
token: token,
limit: l,
offset: o,
patID: chi.URLParam(r, "id"),
}
return req, nil
}
func decodeRemoveScopeRequest(_ context.Context, r *http.Request) (any, error) {
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
return nil, apiutil.ErrUnsupportedContentType
}
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
req := removeScopeReq{
token: token,
id: chi.URLParam(r, "id"),
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, errors.Wrap(errors.ErrMalformedEntity, err)
}
return req, nil
}
func decodeClearAllScopeRequest(_ context.Context, r *http.Request) (any, error) {
token := apiutil.ExtractBearerToken(r)
if strings.HasPrefix(token, patPrefix) {
return nil, apiutil.ErrUnsupportedTokenType
}
return clearAllScopeReq{
token: token,
id: chi.URLParam(r, "id"),
}, nil
}
+2
View File
@@ -9,6 +9,7 @@ import (
"github.com/absmach/supermq"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/auth/api/http/keys"
"github.com/absmach/supermq/auth/api/http/pats"
"github.com/go-chi/chi/v5"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
@@ -18,6 +19,7 @@ func MakeHandler(svc auth.Service, logger *slog.Logger, instanceID string) http.
mux := chi.NewRouter()
mux = keys.MakeHandler(svc, mux, logger)
mux = pats.MakeHandler(svc, mux, logger)
mux.Get("/health", supermq.Health("auth", instanceID))
mux.Handle("/metrics", promhttp.Handler())
-126
View File
@@ -1,126 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
//go:build !test
package api
import (
"context"
"log/slog"
"time"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/policies"
)
var _ auth.Service = (*loggingMiddleware)(nil)
type loggingMiddleware struct {
logger *slog.Logger
svc auth.Service
}
// LoggingMiddleware adds logging facilities to the core service.
func LoggingMiddleware(svc auth.Service, logger *slog.Logger) auth.Service {
return &loggingMiddleware{logger, svc}
}
func (lm *loggingMiddleware) Issue(ctx context.Context, token string, key auth.Key) (tkn auth.Token, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.Group("key",
slog.String("subject", key.Subject),
slog.Any("type", key.Type),
),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("Issue key failed", args...)
return
}
lm.logger.Info("Issue key completed successfully", args...)
}(time.Now())
return lm.svc.Issue(ctx, token, key)
}
func (lm *loggingMiddleware) Revoke(ctx context.Context, token, id string) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("key_id", id),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("Revoke key failed", args...)
return
}
lm.logger.Info("Revoke key completed successfully", args...)
}(time.Now())
return lm.svc.Revoke(ctx, token, id)
}
func (lm *loggingMiddleware) RetrieveKey(ctx context.Context, token, id string) (key auth.Key, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("key_id", id),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("Retrieve key failed", args...)
return
}
lm.logger.Info("Retrieve key completed successfully", args...)
}(time.Now())
return lm.svc.RetrieveKey(ctx, token, id)
}
func (lm *loggingMiddleware) Identify(ctx context.Context, token string) (id auth.Key, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.Group("key",
slog.String("subject", id.Subject),
slog.Any("type", id.Type),
),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("Identify key failed", args...)
return
}
lm.logger.Info("Identify key completed successfully", args...)
}(time.Now())
return lm.svc.Identify(ctx, token)
}
func (lm *loggingMiddleware) Authorize(ctx context.Context, pr policies.Policy) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.Group("object",
slog.String("id", pr.Object),
slog.String("type", pr.ObjectType),
),
slog.Group("subject",
slog.String("id", pr.Subject),
slog.String("kind", pr.SubjectKind),
slog.String("type", pr.SubjectType),
),
slog.String("permission", pr.Permission),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("Authorize failed", args...)
return
}
lm.logger.Info("Authorize completed successfully", args...)
}(time.Now())
return lm.svc.Authorize(ctx, pr)
}
-76
View File
@@ -1,76 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
//go:build !test
package api
import (
"context"
"time"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/policies"
"github.com/go-kit/kit/metrics"
)
var _ auth.Service = (*metricsMiddleware)(nil)
type metricsMiddleware struct {
counter metrics.Counter
latency metrics.Histogram
svc auth.Service
}
// MetricsMiddleware instruments core service by tracking request count and latency.
func MetricsMiddleware(svc auth.Service, counter metrics.Counter, latency metrics.Histogram) auth.Service {
return &metricsMiddleware{
counter: counter,
latency: latency,
svc: svc,
}
}
func (ms *metricsMiddleware) Issue(ctx context.Context, token string, key auth.Key) (auth.Token, error) {
defer func(begin time.Time) {
ms.counter.With("method", "issue_key").Add(1)
ms.latency.With("method", "issue_key").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.Issue(ctx, token, key)
}
func (ms *metricsMiddleware) Revoke(ctx context.Context, token, id string) error {
defer func(begin time.Time) {
ms.counter.With("method", "revoke_key").Add(1)
ms.latency.With("method", "revoke_key").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.Revoke(ctx, token, id)
}
func (ms *metricsMiddleware) RetrieveKey(ctx context.Context, token, id string) (auth.Key, error) {
defer func(begin time.Time) {
ms.counter.With("method", "retrieve_key").Add(1)
ms.latency.With("method", "retrieve_key").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.RetrieveKey(ctx, token, id)
}
func (ms *metricsMiddleware) Identify(ctx context.Context, token string) (auth.Key, error) {
defer func(begin time.Time) {
ms.counter.With("method", "identify").Add(1)
ms.latency.With("method", "identify").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.Identify(ctx, token)
}
func (ms *metricsMiddleware) Authorize(ctx context.Context, pr policies.Policy) error {
defer func(begin time.Time) {
ms.counter.With("method", "authorize").Add(1)
ms.latency.With("method", "authorize").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.Authorize(ctx, pr)
}
+1 -1
View File
@@ -1,4 +1,4 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
package cache
+120
View File
@@ -0,0 +1,120 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package cache
import (
"context"
"fmt"
"time"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/errors"
repoerr "github.com/absmach/supermq/pkg/errors/repository"
"github.com/redis/go-redis/v9"
)
type patCache struct {
client *redis.Client
duration time.Duration
}
func NewPatsCache(client *redis.Client, duration time.Duration) auth.Cache {
return &patCache{
client: client,
duration: duration,
}
}
func (pc *patCache) Save(ctx context.Context, userID string, scopes []auth.Scope) error {
for _, sc := range scopes {
key := generateKey(userID, sc.PatID, sc.OptionalDomainID, sc.EntityType, sc.Operation, sc.EntityID)
if err := pc.client.Set(ctx, key, sc.ID, pc.duration).Err(); err != nil {
return errors.Wrap(repoerr.ErrCreateEntity, err)
}
}
return nil
}
func (pc *patCache) CheckScope(ctx context.Context, userID, patID, optionalDomainID string, entityType auth.EntityType, operation auth.Operation, entityID string) bool {
exactKey := fmt.Sprintf("pat:%s:%s:%s:%s:%s:%s", userID, patID, entityType, optionalDomainID, operation, entityID)
wildcardKey := fmt.Sprintf("pat:%s:%s:%s:%s:%s:*", userID, patID, entityType, operation, operation)
res, err := pc.client.Exists(ctx, exactKey, wildcardKey).Result()
if err != nil {
return false
}
return res > 0
}
func (pc *patCache) Remove(ctx context.Context, userID string, scopeIDs []string) error {
if len(scopeIDs) == 0 {
return repoerr.ErrRemoveEntity
}
pattern := fmt.Sprintf("pat:%s:*", userID)
iter := pc.client.Scan(ctx, 0, pattern, 0).Iterator()
for iter.Next(ctx) {
key := iter.Val()
val, err := pc.client.Get(ctx, key).Result()
if err != nil {
if err == redis.Nil {
continue
}
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
for _, scopeID := range scopeIDs {
if val == scopeID {
if err := pc.client.Del(ctx, key).Err(); err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
break
}
}
}
if err := iter.Err(); err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
return nil
}
func (pc *patCache) RemoveUserAllScope(ctx context.Context, userID string) error {
pattern := fmt.Sprintf("pat:%s:*", userID)
iter := pc.client.Scan(ctx, 0, pattern, 0).Iterator()
for iter.Next(ctx) {
if err := pc.client.Del(ctx, iter.Val()).Err(); err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
}
if err := iter.Err(); err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
return nil
}
func (pc *patCache) RemoveAllScope(ctx context.Context, userID, patID string) error {
pattern := fmt.Sprintf("pat:%s:%s", userID, patID)
iter := pc.client.Scan(ctx, 0, pattern, 0).Iterator()
for iter.Next(ctx) {
if err := pc.client.Del(ctx, iter.Val()).Err(); err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
}
if err := iter.Err(); err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
return nil
}
func generateKey(userID, patID, optionalDomainId string, entityType auth.EntityType, operation auth.Operation, entityID string) string {
return fmt.Sprintf("pat:%s:%s:%s:%s:%s:%s", userID, patID, entityType, optionalDomainId, operation, entityID)
}
+15
View File
@@ -0,0 +1,15 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package auth
// Hasher specifies an API for generating hashes of an arbitrary textual
// content.
type Hasher interface {
// Hash generates the hashed string from plain-text.
Hash(string) (string, error)
// Compare compares plain-text version to the hashed one. An error should
// indicate failed comparison.
Compare(string, string) error
}
+6
View File
@@ -0,0 +1,6 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package hasher contains the domain concept definitions needed to
// support Supermq users password hasher sub-service functionality.
package hasher
+86
View File
@@ -0,0 +1,86 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package hasher
import (
"encoding/base64"
"fmt"
"math/rand"
"strings"
"time"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/errors"
"golang.org/x/crypto/scrypt"
)
var (
errHashToken = errors.New("failed to generate hash for token")
errHashCompare = errors.New("failed to generate hash for given compare string")
errToken = errors.New("given token and hash are not same")
errSalt = errors.New("failed to generate salt")
errInvalidHashStore = errors.New("invalid stored hash format")
errDecode = errors.New("failed to decode")
)
var _ auth.Hasher = (*bcryptHasher)(nil)
type bcryptHasher struct{}
// New instantiates a bcrypt-based hasher implementation.
func New() auth.Hasher {
return &bcryptHasher{}
}
func (bh *bcryptHasher) Hash(token string) (string, error) {
salt, err := generateSalt(25)
if err != nil {
return "", err
}
// N is kept 16384 to make faster and added large salt, since PAT will be access by automation scripts in high frequency.
hash, err := scrypt.Key([]byte(token), salt, 16384, 8, 1, 32)
if err != nil {
return "", errors.Wrap(errHashToken, err)
}
return fmt.Sprintf("%s.%s", base64.StdEncoding.EncodeToString(hash), base64.StdEncoding.EncodeToString(salt)), nil
}
func (bh *bcryptHasher) Compare(plain, hashed string) error {
parts := strings.Split(hashed, ".")
if len(parts) != 2 {
return errInvalidHashStore
}
actHash, err := base64.StdEncoding.DecodeString(parts[0])
if err != nil {
return errors.Wrap(errDecode, err)
}
salt, err := base64.StdEncoding.DecodeString(parts[1])
if err != nil {
return errors.Wrap(errDecode, err)
}
derivedHash, err := scrypt.Key([]byte(plain), salt, 16384, 8, 1, 32)
if err != nil {
return errors.Wrap(errHashCompare, err)
}
if string(derivedHash) == string(actHash) {
return nil
}
return errToken
}
func generateSalt(length int) ([]byte, error) {
rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
salt := make([]byte, length)
_, err := rand.Read(salt)
if err != nil {
return nil, errors.Wrap(errSalt, err)
}
return salt, nil
}
+25 -34
View File
@@ -20,11 +20,10 @@ import (
)
const (
tokenType = "type"
userField = "user"
domainField = "domain"
issuerName = "supermq.auth"
secret = "test"
tokenType = "type"
roleField = "role"
issuerName = "supermq.auth"
secret = "test"
)
var (
@@ -39,10 +38,7 @@ func newToken(issuerName string, key auth.Key) string {
IssuedAt(key.IssuedAt).
Claim(tokenType, "r").
Expiration(key.ExpiresAt)
builder.Claim(userField, key.User)
if key.Domain != "" {
builder.Claim(domainField, key.Domain)
}
builder.Claim(roleField, key.Role)
if key.Subject != "" {
builder.Subject(key.Subject)
}
@@ -73,8 +69,6 @@ func TestIssue(t *testing.T) {
ID: testsutil.GenerateUUID(t),
Type: auth.AccessKey,
Subject: testsutil.GenerateUUID(t),
User: testsutil.GenerateUUID(t),
Domain: testsutil.GenerateUUID(t),
IssuedAt: time.Now().Add(-10 * time.Second).Round(time.Second),
ExpiresAt: time.Now().Add(10 * time.Minute).Round(time.Second),
},
@@ -86,8 +80,6 @@ func TestIssue(t *testing.T) {
ID: testsutil.GenerateUUID(t),
Type: auth.AccessKey,
Subject: testsutil.GenerateUUID(t),
User: testsutil.GenerateUUID(t),
Domain: "",
IssuedAt: time.Now().Add(-10 * time.Second).Round(time.Second),
},
err: nil,
@@ -98,8 +90,16 @@ func TestIssue(t *testing.T) {
ID: testsutil.GenerateUUID(t),
Type: auth.AccessKey,
Subject: "",
User: testsutil.GenerateUUID(t),
Domain: testsutil.GenerateUUID(t),
IssuedAt: time.Now().Add(-10 * time.Second).Round(time.Second),
},
err: nil,
},
{
desc: "issue token without type",
key: auth.Key{
ID: testsutil.GenerateUUID(t),
Type: auth.KeyType(auth.InvitationKey + 1),
Subject: testsutil.GenerateUUID(t),
IssuedAt: time.Now().Add(-10 * time.Second).Round(time.Second),
},
err: nil,
@@ -110,8 +110,6 @@ func TestIssue(t *testing.T) {
ID: testsutil.GenerateUUID(t),
Type: auth.AccessKey,
Subject: "",
User: testsutil.GenerateUUID(t),
Domain: "",
IssuedAt: time.Now().Add(-10 * time.Second).Round(time.Second),
ExpiresAt: time.Now().Add(10 * time.Minute).Round(time.Second),
},
@@ -146,20 +144,18 @@ func TestParse(t *testing.T) {
expToken, err := tokenizer.Issue(expKey)
require.Nil(t, err, fmt.Sprintf("issuing expired key expected to succeed: %s", err))
emptyDomainKey := key()
emptyDomainKey.Domain = ""
emptyDomainToken, err := tokenizer.Issue(emptyDomainKey)
require.Nil(t, err, fmt.Sprintf("issuing user key expected to succeed: %s", err))
emptySubjectKey := key()
emptySubjectKey.Subject = ""
emptySubjectToken, err := tokenizer.Issue(emptySubjectKey)
require.Nil(t, err, fmt.Sprintf("issuing user key expected to succeed: %s", err))
emptyTypeKey := key()
emptyTypeKey.Type = auth.KeyType(auth.InvitationKey + 1)
emptyTypeToken, err := tokenizer.Issue(emptyTypeKey)
require.Nil(t, err, fmt.Sprintf("issuing user key expected to succeed: %s", err))
emptyKey := key()
emptyKey.Domain = ""
emptyKey.Subject = ""
emptyToken, err := tokenizer.Issue(emptyKey)
require.Nil(t, err, fmt.Sprintf("issuing user key expected to succeed: %s", err))
inValidToken := newToken("invalid", key())
@@ -206,12 +202,6 @@ func TestParse(t *testing.T) {
token: newToken(issuerName, key()),
err: authjwt.ErrJSONHandle,
},
{
desc: "parse token with empty domain",
key: emptyDomainKey,
token: emptyDomainToken,
err: nil,
},
{
desc: "parse token with empty subject",
key: emptySubjectKey,
@@ -219,10 +209,10 @@ func TestParse(t *testing.T) {
err: nil,
},
{
desc: "parse token with empty domain and subject",
key: emptyKey,
token: emptyToken,
err: nil,
desc: "parse token with empty type",
key: emptyTypeKey,
token: emptyTypeToken,
err: errors.ErrAuthentication,
},
}
@@ -243,6 +233,7 @@ func key() auth.Key {
ID: "66af4a67-3823-438a-abd7-efdb613eaef6",
Type: auth.AccessKey,
Issuer: "supermq.auth",
Role: auth.UserRole,
Subject: "66af4a67-3823-438a-abd7-efdb613eaef6",
IssuedAt: time.Now().UTC().Add(-10 * time.Second).Round(time.Second),
ExpiresAt: exp,
+45 -8
View File
@@ -6,8 +6,6 @@ package jwt
import (
"context"
"encoding/json"
"fmt"
"strconv"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/errors"
@@ -17,7 +15,14 @@ import (
)
var (
// errInvalidIssuer is returned when the issuer is not supermq.auth.
errInvalidIssuer = errors.New("invalid token issuer value")
// errInvalidType is returned when there is no type field.
errInvalidType = errors.New("invalid token type")
// errInvalidRole is returned when the role is invalid.
errInvalidRole = errors.New("invalid role")
// errInvalidVerified is returned when the verified is invalid.
errInvalidVerified = errors.New("invalid verified")
// errJWTExpiryKey is used to check if the token is expired.
errJWTExpiryKey = errors.New(`"exp" not satisfied`)
// ErrSignJWT indicates an error in signing jwt token.
@@ -32,6 +37,8 @@ const (
issuerName = "supermq.auth"
tokenType = "type"
userField = "user"
RoleField = "role"
VerifiedField = "verified"
oauthProviderField = "oauth_provider"
oauthAccessTokenField = "access_token"
oauthRefreshTokenField = "refresh_token"
@@ -57,7 +64,8 @@ func (tok *tokenizer) Issue(key auth.Key) (string, error) {
IssuedAt(key.IssuedAt).
Claim(tokenType, key.Type).
Expiration(key.ExpiresAt)
builder.Claim(userField, key.User)
builder.Claim(RoleField, key.Role)
builder.Claim(VerifiedField, key.Verified)
if key.Subject != "" {
builder.Subject(key.Subject)
}
@@ -127,19 +135,48 @@ func toKey(tkn jwt.Token) (auth.Key, error) {
tType, ok := tkn.Get(tokenType)
if !ok {
return auth.Key{}, err
return auth.Key{}, errInvalidType
}
ktype, err := strconv.ParseInt(fmt.Sprintf("%v", tType), 10, 64)
if err != nil {
return auth.Key{}, err
kType, ok := tType.(float64)
if !ok {
return auth.Key{}, errInvalidType
}
kt := auth.KeyType(kType)
if !kt.Validate() {
return auth.Key{}, errInvalidType
}
tRole, ok := tkn.Get(RoleField)
if !ok {
return auth.Key{}, errInvalidRole
}
kRole, ok := tRole.(float64)
if !ok {
return auth.Key{}, errInvalidRole
}
tVerified, ok := tkn.Get(VerifiedField)
if !ok {
return auth.Key{}, errInvalidVerified
}
kVerified, ok := tVerified.(bool)
if !ok {
return auth.Key{}, errInvalidVerified
}
kr := auth.Role(kRole)
if !kr.Validate() {
return auth.Key{}, errInvalidRole
}
key.ID = tkn.JwtID()
key.Type = auth.KeyType(ktype)
key.Type = auth.KeyType(kType)
key.Role = auth.Role(kRole)
key.Issuer = tkn.Issuer()
key.Subject = tkn.Subject()
key.IssuedAt = tkn.IssuedAt()
key.ExpiresAt = tkn.Expiration()
key.Verified = kVerified
return key, nil
}
+34 -7
View File
@@ -30,10 +30,16 @@ const (
RecoveryKey
// APIKey enables the one to act on behalf of the user.
APIKey
// PersonalAccessToken represents token generated by user for automation.
PersonalAccessToken
// InvitationKey is a key for inviting new users.
InvitationKey
)
func (kt KeyType) Validate() bool {
return AccessKey <= kt && kt <= InvitationKey
}
func (kt KeyType) String() string {
switch kt {
case AccessKey:
@@ -44,21 +50,45 @@ func (kt KeyType) String() string {
return "recovery"
case APIKey:
return "API"
case PersonalAccessToken:
return "pat"
default:
return "unknown"
}
}
type Role uint32
const (
UserRole Role = iota + 1
AdminRole
)
func (r Role) String() string {
switch r {
case UserRole:
return "user"
case AdminRole:
return "admin"
default:
return "unknown"
}
}
func (r Role) Validate() bool {
return UserRole <= r && r <= AdminRole
}
// Key represents API key.
type Key struct {
ID string `json:"id,omitempty"`
Type KeyType `json:"type,omitempty"`
Issuer string `json:"issuer,omitempty"`
Subject string `json:"subject,omitempty"` // user ID
User string `json:"user,omitempty"`
Domain string `json:"domain,omitempty"` // domain user ID
Role Role `json:"role,omitempty"`
IssuedAt time.Time `json:"issued_at,omitempty"`
ExpiresAt time.Time `json:"expires_at,omitempty"`
Verified bool `json:"verified,omitempty"`
}
func (key Key) String() string {
@@ -67,11 +97,10 @@ func (key Key) String() string {
type: %s,
issuer_id: %s,
subject: %s,
user: %s,
domain: %s,
role: %s,
iat: %v,
eat: %v
}`, key.ID, key.Type, key.Issuer, key.Subject, key.User, key.Domain, key.IssuedAt, key.ExpiresAt)
}`, key.ID, key.Type, key.Issuer, key.Subject, key.Role, key.IssuedAt, key.ExpiresAt)
}
// Expired verifies if the key is expired.
@@ -83,8 +112,6 @@ func (key Key) Expired() bool {
}
// KeyRepository specifies Key persistence API.
//
//go:generate mockery --name KeyRepository --output=./mocks --filename keys.go --quiet --note "Copyright (c) Abstract Machines"
type KeyRepository interface {
// Save persists the Key. A non-nil error is returned to indicate
// operation failure
+9
View File
@@ -0,0 +1,9 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package middleware provides logging metrics and tracing middleware
// for SuperMQ Auth service.
//
// For more details about tracing instrumentation for SuperMQ refer to the
// documentation at https://docs.supermq.abstractmachines.fr/tracing/.
package middleware
+389
View File
@@ -0,0 +1,389 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
//go:build !test
package middleware
import (
"context"
"log/slog"
"time"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/policies"
)
var _ auth.Service = (*loggingMiddleware)(nil)
type loggingMiddleware struct {
logger *slog.Logger
svc auth.Service
}
// NewLogging adds logging facilities to the core service.
func NewLogging(svc auth.Service, logger *slog.Logger) auth.Service {
return &loggingMiddleware{logger, svc}
}
func (lm *loggingMiddleware) Issue(ctx context.Context, token string, key auth.Key) (tkn auth.Token, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.Group("key",
slog.String("subject", key.Subject),
slog.String("type", key.Type.String()),
),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Issue key failed", args...)
return
}
lm.logger.Info("Issue key completed successfully", args...)
}(time.Now())
return lm.svc.Issue(ctx, token, key)
}
func (lm *loggingMiddleware) Revoke(ctx context.Context, token, id string) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("key_id", id),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Revoke key failed", args...)
return
}
lm.logger.Info("Revoke key completed successfully", args...)
}(time.Now())
return lm.svc.Revoke(ctx, token, id)
}
func (lm *loggingMiddleware) RetrieveKey(ctx context.Context, token, id string) (key auth.Key, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("key_id", id),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Retrieve key failed", args...)
return
}
lm.logger.Info("Retrieve key completed successfully", args...)
}(time.Now())
return lm.svc.RetrieveKey(ctx, token, id)
}
func (lm *loggingMiddleware) Identify(ctx context.Context, token string) (id auth.Key, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.Group("key",
slog.String("subject", id.Subject),
slog.String("type", id.Type.String()),
),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Identify key failed", args...)
return
}
lm.logger.Info("Identify key completed successfully", args...)
}(time.Now())
return lm.svc.Identify(ctx, token)
}
func (lm *loggingMiddleware) Authorize(ctx context.Context, pr policies.Policy) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.Group("object",
slog.String("id", pr.Object),
slog.String("type", pr.ObjectType),
),
slog.Group("subject",
slog.String("id", pr.Subject),
slog.String("kind", pr.SubjectKind),
slog.String("type", pr.SubjectType),
),
slog.String("permission", pr.Permission),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Authorize failed", args...)
return
}
lm.logger.Info("Authorize completed successfully", args...)
}(time.Now())
return lm.svc.Authorize(ctx, pr)
}
func (lm *loggingMiddleware) CreatePAT(ctx context.Context, token, name, description string, duration time.Duration) (pa auth.PAT, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("name", name),
slog.String("description", description),
slog.String("pat_duration", duration.String()),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Create PAT failed", args...)
return
}
lm.logger.Info("Create PAT completed successfully", args...)
}(time.Now())
return lm.svc.CreatePAT(ctx, token, name, description, duration)
}
func (lm *loggingMiddleware) UpdatePATName(ctx context.Context, token, patID, name string) (pa auth.PAT, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("pat_id", patID),
slog.String("name", name),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Update PAT name failed", args...)
return
}
lm.logger.Info("Update PAT name completed successfully", args...)
}(time.Now())
return lm.svc.UpdatePATName(ctx, token, patID, name)
}
func (lm *loggingMiddleware) UpdatePATDescription(ctx context.Context, token, patID, description string) (pa auth.PAT, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("pat_id", patID),
slog.String("description", description),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Update PAT description failed", args...)
return
}
lm.logger.Info("Update PAT description completed successfully", args...)
}(time.Now())
return lm.svc.UpdatePATDescription(ctx, token, patID, description)
}
func (lm *loggingMiddleware) RetrievePAT(ctx context.Context, token, patID string) (pa auth.PAT, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("pat_id", patID),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Retrieve PAT failed", args...)
return
}
lm.logger.Info("Retrieve PAT completed successfully", args...)
}(time.Now())
return lm.svc.RetrievePAT(ctx, token, patID)
}
func (lm *loggingMiddleware) ListPATS(ctx context.Context, token string, pm auth.PATSPageMeta) (pp auth.PATSPage, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.Uint64("limit", pm.Limit),
slog.Uint64("offset", pm.Offset),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("List PATS failed", args...)
return
}
lm.logger.Info("List PATS completed successfully", args...)
}(time.Now())
return lm.svc.ListPATS(ctx, token, pm)
}
func (lm *loggingMiddleware) ListScopes(ctx context.Context, token string, pm auth.ScopesPageMeta) (pp auth.ScopesPage, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.Uint64("limit", pm.Limit),
slog.Uint64("offset", pm.Offset),
slog.String("pat_id", pm.PatID),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("List Scopes failed", args...)
return
}
lm.logger.Info("List Scopes completed successfully", args...)
}(time.Now())
return lm.svc.ListScopes(ctx, token, pm)
}
func (lm *loggingMiddleware) DeletePAT(ctx context.Context, token, patID string) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("pat_id", patID),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Delete PAT failed", args...)
return
}
lm.logger.Info("Delete PAT completed successfully", args...)
}(time.Now())
return lm.svc.DeletePAT(ctx, token, patID)
}
func (lm *loggingMiddleware) ResetPATSecret(ctx context.Context, token, patID string, duration time.Duration) (pa auth.PAT, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("pat_id", patID),
slog.String("pat_duration", duration.String()),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Reset PAT secret failed", args...)
return
}
lm.logger.Info("Reset PAT secret completed successfully", args...)
}(time.Now())
return lm.svc.ResetPATSecret(ctx, token, patID, duration)
}
func (lm *loggingMiddleware) RevokePATSecret(ctx context.Context, token, patID string) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("pat_id", patID),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Revoke PAT secret failed", args...)
return
}
lm.logger.Info("Revoke PAT secret completed successfully", args...)
}(time.Now())
return lm.svc.RevokePATSecret(ctx, token, patID)
}
func (lm *loggingMiddleware) RemoveAllPAT(ctx context.Context, token string) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Remove all PAT failed", args...)
return
}
lm.logger.Info("Remove all of PAT completed successfully", args...)
}(time.Now())
return lm.svc.RemoveAllPAT(ctx, token)
}
func (lm *loggingMiddleware) AddScope(ctx context.Context, token, patID string, scopes []auth.Scope) (err error) {
defer func(begin time.Time) {
var groupArgs []any
for _, s := range scopes {
groupArgs = append(groupArgs, slog.String("entity_type", s.EntityType.String()))
groupArgs = append(groupArgs, slog.String("optional_domain_id", s.OptionalDomainID))
groupArgs = append(groupArgs, slog.String("operation", s.Operation.String()))
groupArgs = append(groupArgs, slog.String("entity_id", s.EntityID))
}
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("pat_id", patID),
slog.Group("scope", groupArgs...),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Add PAT scope failed", args...)
return
}
lm.logger.Info("Add PAT scope completed successfully", args...)
}(time.Now())
return lm.svc.AddScope(ctx, token, patID, scopes)
}
func (lm *loggingMiddleware) RemoveScope(ctx context.Context, token, patID string, scopesID ...string) (err error) {
defer func(begin time.Time) {
var groupArgs []any
for _, s := range scopesID {
groupArgs = append(groupArgs, slog.String("scope_id", s))
}
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("pat_id", patID),
slog.Group("scope", groupArgs...),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Remove entry from PAT scope failed", args...)
return
}
lm.logger.Info("Remove entry from PAT scope completed successfully", args...)
}(time.Now())
return lm.svc.RemoveScope(ctx, token, patID, scopesID...)
}
func (lm *loggingMiddleware) RemovePATAllScope(ctx context.Context, token, patID string) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("pat_id", patID),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Remove all scopes from PAT failed", args...)
return
}
lm.logger.Info("Remove all scopes from PAT completed successfully", args...)
}(time.Now())
return lm.svc.RemovePATAllScope(ctx, token, patID)
}
func (lm *loggingMiddleware) IdentifyPAT(ctx context.Context, paToken string) (pa auth.PAT, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Identify PAT failed", args...)
return
}
lm.logger.Info("Identify PAT completed successfully", args...)
}(time.Now())
return lm.svc.IdentifyPAT(ctx, paToken)
}
func (lm *loggingMiddleware) AuthorizePAT(ctx context.Context, userID, patID string, entityType auth.EntityType, optionalDomainID string, operation auth.Operation, entityID string) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("entity_type", entityType.String()),
slog.String("optional_domain_id", optionalDomainID),
slog.String("operation", operation.String()),
slog.String("entities", entityID),
}
if err != nil {
args = append(args, slog.String("error", err.Error()))
lm.logger.Warn("Authorize PAT failed complete successfully", args...)
return
}
lm.logger.Info("Authorize PAT completed successfully", args...)
}(time.Now())
return lm.svc.AuthorizePAT(ctx, userID, patID, entityType, optionalDomainID, operation, entityID)
}
+196
View File
@@ -0,0 +1,196 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
//go:build !test
package middleware
import (
"context"
"time"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/policies"
"github.com/go-kit/kit/metrics"
)
var _ auth.Service = (*metricsMiddleware)(nil)
type metricsMiddleware struct {
counter metrics.Counter
latency metrics.Histogram
svc auth.Service
}
// NewMetrics instruments core service by tracking request count and latency.
func NewMetrics(svc auth.Service, counter metrics.Counter, latency metrics.Histogram) auth.Service {
return &metricsMiddleware{
counter: counter,
latency: latency,
svc: svc,
}
}
func (ms *metricsMiddleware) Issue(ctx context.Context, token string, key auth.Key) (auth.Token, error) {
defer func(begin time.Time) {
ms.counter.With("method", "issue_key").Add(1)
ms.latency.With("method", "issue_key").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.Issue(ctx, token, key)
}
func (ms *metricsMiddleware) Revoke(ctx context.Context, token, id string) error {
defer func(begin time.Time) {
ms.counter.With("method", "revoke_key").Add(1)
ms.latency.With("method", "revoke_key").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.Revoke(ctx, token, id)
}
func (ms *metricsMiddleware) RetrieveKey(ctx context.Context, token, id string) (auth.Key, error) {
defer func(begin time.Time) {
ms.counter.With("method", "retrieve_key").Add(1)
ms.latency.With("method", "retrieve_key").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.RetrieveKey(ctx, token, id)
}
func (ms *metricsMiddleware) Identify(ctx context.Context, token string) (auth.Key, error) {
defer func(begin time.Time) {
ms.counter.With("method", "identify").Add(1)
ms.latency.With("method", "identify").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.Identify(ctx, token)
}
func (ms *metricsMiddleware) Authorize(ctx context.Context, pr policies.Policy) error {
defer func(begin time.Time) {
ms.counter.With("method", "authorize").Add(1)
ms.latency.With("method", "authorize").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.Authorize(ctx, pr)
}
func (ms *metricsMiddleware) CreatePAT(ctx context.Context, token, name, description string, duration time.Duration) (auth.PAT, error) {
defer func(begin time.Time) {
ms.counter.With("method", "create_pat").Add(1)
ms.latency.With("method", "create_pat").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.CreatePAT(ctx, token, name, description, duration)
}
func (ms *metricsMiddleware) UpdatePATName(ctx context.Context, token, patID, name string) (auth.PAT, error) {
defer func(begin time.Time) {
ms.counter.With("method", "update_pat_name").Add(1)
ms.latency.With("method", "update_pat_name").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.UpdatePATName(ctx, token, patID, name)
}
func (ms *metricsMiddleware) UpdatePATDescription(ctx context.Context, token, patID, description string) (auth.PAT, error) {
defer func(begin time.Time) {
ms.counter.With("method", "update_pat_description").Add(1)
ms.latency.With("method", "update_pat_description").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.UpdatePATDescription(ctx, token, patID, description)
}
func (ms *metricsMiddleware) RetrievePAT(ctx context.Context, token, patID string) (auth.PAT, error) {
defer func(begin time.Time) {
ms.counter.With("method", "retrieve_pat").Add(1)
ms.latency.With("method", "retrieve_pat").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.RetrievePAT(ctx, token, patID)
}
func (ms *metricsMiddleware) ListPATS(ctx context.Context, token string, pm auth.PATSPageMeta) (auth.PATSPage, error) {
defer func(begin time.Time) {
ms.counter.With("method", "list_pats").Add(1)
ms.latency.With("method", "list_pats").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.ListPATS(ctx, token, pm)
}
func (ms *metricsMiddleware) ListScopes(ctx context.Context, token string, pm auth.ScopesPageMeta) (auth.ScopesPage, error) {
defer func(begin time.Time) {
ms.counter.With("method", "list_scopes").Add(1)
ms.latency.With("method", "list_scopes").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.ListScopes(ctx, token, pm)
}
func (ms *metricsMiddleware) DeletePAT(ctx context.Context, token, patID string) error {
defer func(begin time.Time) {
ms.counter.With("method", "delete_pat").Add(1)
ms.latency.With("method", "delete_pat").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.DeletePAT(ctx, token, patID)
}
func (ms *metricsMiddleware) ResetPATSecret(ctx context.Context, token, patID string, duration time.Duration) (auth.PAT, error) {
defer func(begin time.Time) {
ms.counter.With("method", "reset_pat_secret").Add(1)
ms.latency.With("method", "reset_pat_secret").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.ResetPATSecret(ctx, token, patID, duration)
}
func (ms *metricsMiddleware) RevokePATSecret(ctx context.Context, token, patID string) error {
defer func(begin time.Time) {
ms.counter.With("method", "revoke_pat_secret").Add(1)
ms.latency.With("method", "revoke_pat_secret").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.RevokePATSecret(ctx, token, patID)
}
func (ms *metricsMiddleware) RemoveAllPAT(ctx context.Context, token string) error {
defer func(begin time.Time) {
ms.counter.With("method", "clear_all_pat").Add(1)
ms.latency.With("method", "clear_all_pat").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.RemoveAllPAT(ctx, token)
}
func (ms *metricsMiddleware) AddScope(ctx context.Context, token, patID string, scopes []auth.Scope) error {
defer func(begin time.Time) {
ms.counter.With("method", "add_pat_scope").Add(1)
ms.latency.With("method", "add_pat_scope").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.AddScope(ctx, token, patID, scopes)
}
func (ms *metricsMiddleware) RemoveScope(ctx context.Context, token, patID string, scopesID ...string) error {
defer func(begin time.Time) {
ms.counter.With("method", "remove_pat_scope").Add(1)
ms.latency.With("method", "remove_pat_scope").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.RemoveScope(ctx, token, patID, scopesID...)
}
func (ms *metricsMiddleware) RemovePATAllScope(ctx context.Context, token, patID string) error {
defer func(begin time.Time) {
ms.counter.With("method", "clear_pat_all_scope").Add(1)
ms.latency.With("method", "clear_pat_all_scope").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.RemovePATAllScope(ctx, token, patID)
}
func (ms *metricsMiddleware) IdentifyPAT(ctx context.Context, paToken string) (auth.PAT, error) {
defer func(begin time.Time) {
ms.counter.With("method", "identify_pat").Add(1)
ms.latency.With("method", "identify_pat").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.IdentifyPAT(ctx, paToken)
}
func (ms *metricsMiddleware) AuthorizePAT(ctx context.Context, userID, patID string, entityType auth.EntityType, optionalDomainID string, operation auth.Operation, entityID string) error {
defer func(begin time.Time) {
ms.counter.With("method", "authorize_pat").Add(1)
ms.latency.With("method", "authorize_pat").Observe(time.Since(begin).Seconds())
}(time.Now())
return ms.svc.AuthorizePAT(ctx, userID, patID, entityType, optionalDomainID, operation, entityID)
}
+217
View File
@@ -0,0 +1,217 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package middleware
import (
"context"
"fmt"
"time"
"github.com/absmach/supermq/auth"
"github.com/absmach/supermq/pkg/policies"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
var _ auth.Service = (*tracingMiddleware)(nil)
type tracingMiddleware struct {
tracer trace.Tracer
svc auth.Service
}
// NewTracing returns a new auth service with tracing capabilities.
func NewTracing(svc auth.Service, tracer trace.Tracer) auth.Service {
return &tracingMiddleware{tracer, svc}
}
func (tm *tracingMiddleware) Issue(ctx context.Context, token string, key auth.Key) (auth.Token, error) {
ctx, span := tm.tracer.Start(ctx, "issue", trace.WithAttributes(
attribute.String("type", fmt.Sprintf("%d", key.Type)),
attribute.String("subject", key.Subject),
))
defer span.End()
return tm.svc.Issue(ctx, token, key)
}
func (tm *tracingMiddleware) Revoke(ctx context.Context, token, id string) error {
ctx, span := tm.tracer.Start(ctx, "revoke", trace.WithAttributes(
attribute.String("id", id),
))
defer span.End()
return tm.svc.Revoke(ctx, token, id)
}
func (tm *tracingMiddleware) RetrieveKey(ctx context.Context, token, id string) (auth.Key, error) {
ctx, span := tm.tracer.Start(ctx, "retrieve_key", trace.WithAttributes(
attribute.String("id", id),
))
defer span.End()
return tm.svc.RetrieveKey(ctx, token, id)
}
func (tm *tracingMiddleware) Identify(ctx context.Context, token string) (auth.Key, error) {
ctx, span := tm.tracer.Start(ctx, "identify")
defer span.End()
return tm.svc.Identify(ctx, token)
}
func (tm *tracingMiddleware) Authorize(ctx context.Context, pr policies.Policy) error {
ctx, span := tm.tracer.Start(ctx, "authorize", trace.WithAttributes(
attribute.String("subject", pr.Subject),
attribute.String("subject_type", pr.SubjectType),
attribute.String("subject_relation", pr.SubjectRelation),
attribute.String("object", pr.Object),
attribute.String("object_type", pr.ObjectType),
attribute.String("relation", pr.Relation),
attribute.String("permission", pr.Permission),
))
defer span.End()
return tm.svc.Authorize(ctx, pr)
}
func (tm *tracingMiddleware) CreatePAT(ctx context.Context, token, name, description string, duration time.Duration) (auth.PAT, error) {
ctx, span := tm.tracer.Start(ctx, "create_pat", trace.WithAttributes(
attribute.String("name", name),
attribute.String("description", description),
attribute.String("duration", duration.String()),
))
defer span.End()
return tm.svc.CreatePAT(ctx, token, name, description, duration)
}
func (tm *tracingMiddleware) UpdatePATName(ctx context.Context, token, patID, name string) (auth.PAT, error) {
ctx, span := tm.tracer.Start(ctx, "update_pat_name", trace.WithAttributes(
attribute.String("pat_id", patID),
attribute.String("name", name),
))
defer span.End()
return tm.svc.UpdatePATName(ctx, token, patID, name)
}
func (tm *tracingMiddleware) UpdatePATDescription(ctx context.Context, token, patID, description string) (auth.PAT, error) {
ctx, span := tm.tracer.Start(ctx, "update_pat_description", trace.WithAttributes(
attribute.String("pat_id", patID),
attribute.String("description", description),
))
defer span.End()
return tm.svc.UpdatePATDescription(ctx, token, patID, description)
}
func (tm *tracingMiddleware) RetrievePAT(ctx context.Context, token, patID string) (auth.PAT, error) {
ctx, span := tm.tracer.Start(ctx, "retrieve_pat", trace.WithAttributes(
attribute.String("pat_id", patID),
))
defer span.End()
return tm.svc.RetrievePAT(ctx, token, patID)
}
func (tm *tracingMiddleware) ListPATS(ctx context.Context, token string, pm auth.PATSPageMeta) (auth.PATSPage, error) {
ctx, span := tm.tracer.Start(ctx, "list_pat", trace.WithAttributes(
attribute.Int64("limit", int64(pm.Limit)),
attribute.Int64("offset", int64(pm.Offset)),
))
defer span.End()
return tm.svc.ListPATS(ctx, token, pm)
}
func (tm *tracingMiddleware) ListScopes(ctx context.Context, token string, pm auth.ScopesPageMeta) (auth.ScopesPage, error) {
ctx, span := tm.tracer.Start(ctx, "list_scopes", trace.WithAttributes(
attribute.Int64("limit", int64(pm.Limit)),
attribute.Int64("offset", int64(pm.Offset)),
))
defer span.End()
return tm.svc.ListScopes(ctx, token, pm)
}
func (tm *tracingMiddleware) DeletePAT(ctx context.Context, token, patID string) error {
ctx, span := tm.tracer.Start(ctx, "delete_pat", trace.WithAttributes(
attribute.String("pat_id", patID),
))
defer span.End()
return tm.svc.DeletePAT(ctx, token, patID)
}
func (tm *tracingMiddleware) ResetPATSecret(ctx context.Context, token, patID string, duration time.Duration) (auth.PAT, error) {
ctx, span := tm.tracer.Start(ctx, "reset_pat_secret", trace.WithAttributes(
attribute.String("pat_id", patID),
attribute.String("duration", duration.String()),
))
defer span.End()
return tm.svc.ResetPATSecret(ctx, token, patID, duration)
}
func (tm *tracingMiddleware) RevokePATSecret(ctx context.Context, token, patID string) error {
ctx, span := tm.tracer.Start(ctx, "revoke_pat_secret", trace.WithAttributes(
attribute.String("pat_id", patID),
))
defer span.End()
return tm.svc.RevokePATSecret(ctx, token, patID)
}
func (tm *tracingMiddleware) RemoveAllPAT(ctx context.Context, token string) error {
ctx, span := tm.tracer.Start(ctx, "clear_all_pat")
defer span.End()
return tm.svc.RemoveAllPAT(ctx, token)
}
func (tm *tracingMiddleware) AddScope(ctx context.Context, token, patID string, scopes []auth.Scope) error {
var attributes []attribute.KeyValue
for _, s := range scopes {
attributes = append(attributes, attribute.String("entity_type", s.EntityType.String()))
attributes = append(attributes, attribute.String("optional_domain_id", s.OptionalDomainID))
attributes = append(attributes, attribute.String("operation", s.Operation.String()))
attributes = append(attributes, attribute.String("entity_id", s.EntityID))
}
attributes = append(attributes, attribute.String("pat_id", patID))
ctx, span := tm.tracer.Start(ctx, "add_pat_scope", trace.WithAttributes(attributes...))
defer span.End()
return tm.svc.AddScope(ctx, token, patID, scopes)
}
func (tm *tracingMiddleware) RemoveScope(ctx context.Context, token, patID string, scopesID ...string) error {
var attributes []attribute.KeyValue
for _, s := range scopesID {
attributes = append(attributes, attribute.String("scope_id", s))
}
attributes = append(attributes, attribute.String("pat_id", patID))
ctx, span := tm.tracer.Start(ctx, "remove_pat_scope", trace.WithAttributes(attributes...))
defer span.End()
return tm.svc.RemoveScope(ctx, token, patID, scopesID...)
}
func (tm *tracingMiddleware) RemovePATAllScope(ctx context.Context, token, patID string) error {
ctx, span := tm.tracer.Start(ctx, "clear_pat_all_scope", trace.WithAttributes(
attribute.String("pat_id", patID),
))
defer span.End()
return tm.svc.RemovePATAllScope(ctx, token, patID)
}
func (tm *tracingMiddleware) IdentifyPAT(ctx context.Context, paToken string) (auth.PAT, error) {
ctx, span := tm.tracer.Start(ctx, "identity_pat")
defer span.End()
return tm.svc.IdentifyPAT(ctx, paToken)
}
func (tm *tracingMiddleware) AuthorizePAT(ctx context.Context, userID, patID string, entityType auth.EntityType, optionalDomainID string, operation auth.Operation, entityID string) error {
ctx, span := tm.tracer.Start(ctx, "authorize_pat", trace.WithAttributes(
attribute.String("pat_id", patID),
attribute.String("entity_type", entityType.String()),
attribute.String("optional_domain_id", optionalDomainID),
attribute.String("operation", operation.String()),
attribute.String("entities", entityID),
))
defer span.End()
return tm.svc.AuthorizePAT(ctx, userID, patID, entityType, optionalDomainID, operation, entityID)
}

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