mirror of
https://github.com/absmach/magistrala.git
synced 2026-08-07 15:25:48 +00:00
Compare commits
402 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 65c6a4d8f4 | |||
| ec223e7467 | |||
| aa3cc3d7ee | |||
| 9650dde716 | |||
| d02747a56f | |||
| dc0df1c955 | |||
| 64b4497ad4 | |||
| 1b26264495 | |||
| 69366d77cc | |||
| fa8862cbc8 | |||
| 15b8901853 | |||
| 9258237cb6 | |||
| 2adeecd9ec | |||
| c5eee6d8fd | |||
| 648edbd386 | |||
| 35fb296318 | |||
| a98777b191 | |||
| 3c693a7b41 | |||
| c230a24b7d | |||
| 42b2a8c166 | |||
| 6468ebe749 | |||
| 1adbe1ff24 | |||
| 27995cb093 | |||
| 5833bafbee | |||
| 6394908b2c | |||
| 0e0598c6d8 | |||
| 3e400da5ad | |||
| 2112281171 | |||
| 6f40c7fa1e | |||
| b0e9e43b9e | |||
| bc7727c275 | |||
| 8d1c3c41b5 | |||
| d84df8604f | |||
| d4d8bc5351 | |||
| ac9bc9aad6 | |||
| 4b83301f69 | |||
| b746a8679f | |||
| e6022542b9 | |||
| 6c77e1b738 | |||
| 04774ae972 | |||
| ae7c93020a | |||
| b031dc08b8 | |||
| 0465ceb7a3 | |||
| af424ee2cb | |||
| 96a15b32dd | |||
| 61f1e9aca2 | |||
| 29f7063c15 | |||
| 1f48a73677 | |||
| cd9cb9e1d5 | |||
| 8d9e92f228 | |||
| ad685c27ad | |||
| 44485cacec | |||
| 7fac6ff4c4 | |||
| 1930a0c8f2 | |||
| 9eac9366ba | |||
| ad191c4609 | |||
| 1d935f0519 | |||
| bc1ccace4a | |||
| 89fdb4e6c7 | |||
| 44e44639aa | |||
| d31c66174e | |||
| e6d7a07277 | |||
| a2ea92a5ba | |||
| 3320a716f3 | |||
| a70b838f1c | |||
| c50221a042 | |||
| 1efa8b5bce | |||
| e57ad79cd4 | |||
| 22616911d2 | |||
| 766bb5519a | |||
| fbcdef9693 | |||
| 9aacde7c5b | |||
| cdf26051f6 | |||
| a9a412e909 | |||
| 0754fa1126 | |||
| ec75f4eadb | |||
| af35396601 | |||
| 6a27594751 | |||
| 555d89d358 | |||
| c3c9dcf318 | |||
| 5a75772f62 | |||
| b9ac94f058 | |||
| 8ab1f4c408 | |||
| e842bfaab6 | |||
| 886cd63415 | |||
| 9cd22910d8 | |||
| 906e365adf | |||
| 8e7e897906 | |||
| 4b50ef93a2 | |||
| 73c2d76b58 | |||
| 473338527a | |||
| 12d1a0de32 | |||
| b4e0e89c38 | |||
| 6f5e535b30 | |||
| fb1062a98a | |||
| c56a5ae577 | |||
| a19cd9c97b | |||
| 0e1a090f16 | |||
| ef712443e1 | |||
| 248b708909 | |||
| c63c936b36 | |||
| 4927333691 | |||
| 5acc8f96a6 | |||
| 9d91740063 | |||
| 1951f206cb | |||
| 441feb8578 | |||
| 7d11f16988 | |||
| 2e3f52fdbf | |||
| b942a42271 | |||
| 0178594c25 | |||
| 3dbd617ed0 | |||
| 8188da16b3 | |||
| bc7b988098 | |||
| a0b3970ad6 | |||
| 0f20663cfb | |||
| 4dc98763a6 | |||
| 230be1d13b | |||
| 99493d86ff | |||
| 4ffb1fe422 | |||
| f4417ecb78 | |||
| 9b77130f6e | |||
| 71ea84c3ec | |||
| 36c138688d | |||
| 86afe1736f | |||
| 8e70e1113e | |||
| a379d11035 | |||
| 45a5c42ea4 | |||
| 99a55a6e24 | |||
| 6e404caa32 | |||
| 898048cb8b | |||
| 0794c2828e | |||
| 7be4ec6890 | |||
| 5669e8a76e | |||
| d4dc7ffe35 | |||
| b6080bc42b | |||
| 0dea465fb3 | |||
| 879225f7a8 | |||
| f8a7a75486 | |||
| fb0b188d4e | |||
| 376bc8b9c4 | |||
| da319a1aa9 | |||
| 2ab3db79e5 | |||
| 33e8d4f47e | |||
| 902e85e648 | |||
| afb28667c4 | |||
| 26feb34f8d | |||
| bdfdb67998 | |||
| 1c0400d3a5 | |||
| fa5b6b86c6 | |||
| 16f1b411ec | |||
| be66701b15 | |||
| 0a18a580eb | |||
| a0044c51be | |||
| 788d8334f7 | |||
| 7ecdd7ebe3 | |||
| dda01ff4a1 | |||
| 5d04de4ffa | |||
| f6e8db4c09 | |||
| 0f9ae05615 | |||
| bcba9e962e | |||
| 191f8a1e0f | |||
| 0d1aafcbbf | |||
| 9a194a86df | |||
| 668013cbad | |||
| d83f0b8559 | |||
| c198e8093b | |||
| 12a562284e | |||
| 54c1ff0587 | |||
| d9cf3851a1 | |||
| 9abdf39fd6 | |||
| d8e895970c | |||
| f7f399a5a5 | |||
| 3a1b9ce20b | |||
| 8d04e7adbe | |||
| 707ca54ef9 | |||
| ca93b8865a | |||
| 86dd4ede3a | |||
| 5b7b759131 | |||
| 2aa247b3c3 | |||
| ec126a5976 | |||
| c8814237cf | |||
| e98b6576f1 | |||
| c429b1d5ff | |||
| 09de0cf2f5 | |||
| a01d933218 | |||
| d8b7af424e | |||
| 798ed3a2dd | |||
| d3c9e0bbcd | |||
| b69947fc57 | |||
| e4553f27d1 | |||
| cf68a07b00 | |||
| c691fb779a | |||
| a93fccc234 | |||
| 4bea349b04 | |||
| ab41689a9b | |||
| 921e5111b5 | |||
| 21c7b1019e | |||
| d64a74b1be | |||
| 343a771c4f | |||
| 5e96516bf6 | |||
| 582b764679 | |||
| 56528ee68a | |||
| 8856a26869 | |||
| b2eb51c155 | |||
| a95d1bb672 | |||
| 5b572cd5fc | |||
| 8fce6fc8d4 | |||
| d2eabd1836 | |||
| 8c3f621e21 | |||
| 0275c8a5c4 | |||
| 0dd25d7140 | |||
| 079749b3e8 | |||
| c0fd0f410f | |||
| 58753f60d8 | |||
| 04f6117e36 | |||
| 7f4633a3d1 | |||
| d6c260b803 | |||
| 2dba6e644f | |||
| a7d2acb591 | |||
| 2b5a670bef | |||
| 16eff6bebb | |||
| c7c224b5f1 | |||
| 86a8f49e82 | |||
| 9a9e22fbce | |||
| d7d059767b | |||
| 3b38863b61 | |||
| c092e4c888 | |||
| 17a884f7e9 | |||
| 920d775965 | |||
| 7a3c598fb9 | |||
| 8b185cf48c | |||
| 0c7ec7c197 | |||
| 7b13473af8 | |||
| b586d988e6 | |||
| 16ac66c35f | |||
| ecf78a36ba | |||
| 39bb9f5240 | |||
| f76332ef71 | |||
| ed367fb1e5 | |||
| b04fb5cd97 | |||
| 5ea3cbd014 | |||
| cc9fc70d6d | |||
| 8aa5668a73 | |||
| bd9e0c9b5a | |||
| f79cce34fa | |||
| fc02c26a84 | |||
| c14bb6e18a | |||
| 62f4599140 | |||
| 56fa8aee84 | |||
| 6d7100b8ec | |||
| 602025b48b | |||
| 0e571d1905 | |||
| 757ad31f92 | |||
| 01f20a29d2 | |||
| 5fd1d9b431 | |||
| 6151be72ce | |||
| 299cee7771 | |||
| a01d2571de | |||
| 1c3ffba300 | |||
| ba9d65898f | |||
| 814f19390d | |||
| af8caa4cc8 | |||
| ff55a7625a | |||
| 8e5daf735d | |||
| f2006ae97a | |||
| efb392f77b | |||
| 739730efe5 | |||
| 05e72a5932 | |||
| a1e4b51d55 | |||
| 006a1fb0f4 | |||
| e14eee0ac5 | |||
| 49fd8448c0 | |||
| b79fdb1534 | |||
| 3931ecabdb | |||
| 7a3a55d399 | |||
| 340098cec3 | |||
| 12b41e3ab0 | |||
| ce570be40e | |||
| 5e77512009 | |||
| 321e38590c | |||
| 7ae2f7de00 | |||
| 056dd34f9b | |||
| 623b9910d5 | |||
| 6011cad546 | |||
| e56b86823e | |||
| 878860d249 | |||
| 3ff3469455 | |||
| cca5e27de7 | |||
| 7e1b53bf3e | |||
| ddb3f9ba6d | |||
| 3b675a7ab3 | |||
| f6b3938f96 | |||
| b0493e03af | |||
| 1ad754d933 | |||
| 001c8255eb | |||
| 1e4341a6ec | |||
| 2bee2efae5 | |||
| 065e764387 | |||
| e7032a6313 | |||
| b23a8c20eb | |||
| 5cc3c1b4fa | |||
| 88f7172fb4 | |||
| fd76a03257 | |||
| adf94adc7b | |||
| 98bc206169 | |||
| 17b5224090 | |||
| 56829c15d8 | |||
| df0f9068d6 | |||
| de05aa7f88 | |||
| 9997d0c77f | |||
| d4c8383266 | |||
| 986bc38a19 | |||
| f96876fe04 | |||
| a5bf63c2c6 | |||
| a4e4527b04 | |||
| 506f67f222 | |||
| 5c0a0237d7 | |||
| 2a86caeb3d | |||
| eaaba5beeb | |||
| 72c762f9cb | |||
| 972fa0b25b | |||
| da6e3e17a6 | |||
| db553d328a | |||
| 3fc7868759 | |||
| 62a3578e0d | |||
| 42f48b41ba | |||
| 7667eee725 | |||
| 597ad23ba1 | |||
| 838cfd59a6 | |||
| 984d67eaa1 | |||
| 6121c18088 | |||
| 392940cfa8 | |||
| 118d85f1e8 | |||
| 236b841182 | |||
| da17597121 | |||
| bd44d1e95a | |||
| 67ab52db90 | |||
| cff6e7f085 | |||
| 7c6bc9cd7e | |||
| 484de372ec | |||
| 07dbb86203 | |||
| 53cb10bb89 | |||
| e69730d9d6 | |||
| ef328369b8 | |||
| e5b2fa2ec7 | |||
| 97f8092868 | |||
| d2dbc4c44c | |||
| d77d005659 | |||
| 104c5b3da4 | |||
| 53e39a1dc6 | |||
| 3cb41fa6e7 | |||
| 88d583bfb1 | |||
| a8b12e4461 | |||
| bc6339bf52 | |||
| 15d8e94678 | |||
| 250070dc15 | |||
| f7ee4f103c | |||
| fbbe5ff767 | |||
| 5d755990b7 | |||
| fdea1a753e | |||
| d02d63d1eb | |||
| 153d230907 | |||
| 3a11b54394 | |||
| 6fd7e3de63 | |||
| 33407fad16 | |||
| a9169276e5 | |||
| df5d752c4b | |||
| cd73d36bdf | |||
| 2b2d8b8a5c | |||
| a052559983 | |||
| 8de72f88f4 | |||
| d89c199f3a | |||
| 378da932b5 | |||
| c89cb41c5b | |||
| ca0f7ca3e8 | |||
| 6abc52d074 | |||
| f12aacd1da | |||
| c32d40636d | |||
| 6b16535958 | |||
| 58ba597c62 | |||
| 8e552d0a96 | |||
| 4f73a52192 | |||
| 7486317363 | |||
| 7ac7b1f9c6 | |||
| 10c6140e3c | |||
| c50bf5bebf | |||
| 0e2ae5e5e1 | |||
| 1474da8b2e | |||
| e95d1bfbcf | |||
| f0d014eba2 | |||
| 9e6da193c8 | |||
| e8e17f5530 | |||
| 0d126c3be0 | |||
| d46c8d71a0 | |||
| 99b3e67918 | |||
| d6aa51bf24 | |||
| f288c77893 | |||
| f7d0513ad5 | |||
| 8c93dae2ba | |||
| 42802703d4 | |||
| e8e8a4bd8a | |||
| e8d77679e4 |
@@ -5,6 +5,10 @@
|
||||
coverage:
|
||||
ignore:
|
||||
- "tools/*"
|
||||
- "cmd/*"
|
||||
- "coap/*"
|
||||
- "**/mocks*"
|
||||
- "*/mocks/*"
|
||||
- "*/middleware/*"
|
||||
- "pkg/sid/mock.go"
|
||||
- "pkg/tracing/utils.go"
|
||||
- "pkg/prometheus/*"
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,117 +1,96 @@
|
||||
# SuperMQ
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/absmach/supermq/actions/workflows/check-license.yaml)
|
||||
[](https://github.com/absmach/supermq/actions/workflows/check-generated-files.yml)
|
||||
[](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/)**
|
||||
|
||||
[](https://github.com/absmach/supermq/actions/workflows/build.yaml)
|
||||
[](https://github.com/absmach/supermq/actions/workflows/check-license.yaml)
|
||||
[](https://github.com/absmach/supermq/actions/workflows/check-generated-files.yaml)
|
||||
[](https://goreportcard.com/report/github.com/absmach/supermq)
|
||||
[](https://codecov.io/gh/absmach/supermq)
|
||||
[](LICENSE)
|
||||
[](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
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
+40
-2
@@ -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
|
||||
}
|
||||
+2
-2
@@ -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
|
||||
}
|
||||
+78
-1
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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:
|
||||
@@ -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)
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package api
|
||||
package cache
|
||||
Vendored
+120
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user