diff --git a/content/docs/dev-guide/authorization.mdx b/content/docs/dev-guide/authorization.mdx index 838321b..9eec825 100644 --- a/content/docs/dev-guide/authorization.mdx +++ b/content/docs/dev-guide/authorization.mdx @@ -16,7 +16,8 @@ image: /img/mg-preview.png No SpiceDB container exists in `docker-compose.yaml`, and the old per-entity relations/permissions schema and REST role management API (`///roles`) no longer apply. - Authorization is now owned entirely by **Atom** — see [Auth](/dev-guide/services/auth). + Authorization is now owned entirely by **Atom** — see [Overview](/dev-guide/entities) for its + entity model. ## The model diff --git a/content/docs/dev-guide/dev-tools/authentication.mdx b/content/docs/dev-guide/dev-tools/authentication.mdx index 6d0ed76..79bc5a9 100644 --- a/content/docs/dev-guide/dev-tools/authentication.mdx +++ b/content/docs/dev-guide/dev-tools/authentication.mdx @@ -197,7 +197,7 @@ In most of the cases, HTTPS, WSS, MQTTS or secure CoAP are secure enough. Howeve AUTH=x509 docker-compose -f docker/docker-compose.yml up -d ``` -Mutual authentication includes client-side certificates. Certificates can be generated using the simple script provided in the [SSL Makefile][ssl-makefile]. In order to create a valid certificate, you need to create Magistrala client using the process described in the [provisioning section][provision]. After that, you need to fetch created client secret. Client secret will be used to create x.509 certificate for the corresponding client. To create a certificate, execute the following commands: +Mutual authentication includes client-side certificates. Certificates can be generated using the simple script provided in the [SSL Makefile][ssl-makefile]. In order to create a valid certificate, you need to create Magistrala client using the process described in the provisioning section. After that, you need to fetch created client secret. Client secret will be used to create x.509 certificate for the corresponding client. To create a certificate, execute the following commands: ```bash cd docker/ssl @@ -315,7 +315,6 @@ mosquitto_sub -I -u -P --cafile docker [messaging]: /dev-guide/dev-tools/messaging [rf5280]: https://tools.ietf.org/html/rfc5280 [ssl-makefile]: https://github.com/absmach/magistrala/blob/main/docker/ssl/Makefile -[provision]: /dev-guide/services/provision [openssl]: https://www.openssl.org/ [vault]: https://www.vaultproject.io/ [oidc]: https://openid.net/connect/ diff --git a/content/docs/dev-guide/edge.mdx b/content/docs/dev-guide/edge.mdx index c6631cb..59ce054 100644 --- a/content/docs/dev-guide/edge.mdx +++ b/content/docs/dev-guide/edge.mdx @@ -42,7 +42,7 @@ Agent can be used to control deployed services as well as to monitor their livel ## Agent -Agent is service that is used to manage gateways that are connected to Magistrala in cloud. It provides a way to send commands to gateway and receive response via mqtt. There are two types of channels used for **Agent** `data` and `control`. Over the `control` we are sending commands and receiving response from commands. Data collected from sensors connected to gateway are being sent over `data` channel. Agent is able to configure itself provided that [bootstrap server][bootstrap] is running, it will retrieve configuration from bootstrap server provided few arguments - `external_id` and `external_key` see [bootstraping][bootstraping]. +Agent is service that is used to manage gateways that are connected to Magistrala in cloud. It provides a way to send commands to gateway and receive response via mqtt. There are two types of channels used for **Agent** `data` and `control`. Over the `control` we are sending commands and receiving response from commands. Data collected from sensors connected to gateway are being sent over `data` channel. Agent is able to configure itself provided that [bootstrap server](/dev-guide/services/bootstrap) is running, it will retrieve configuration from bootstrap server provided few arguments - `external_id` and `external_key` see [bootstrapping](/dev-guide/services/bootstrap#device-bootstrap). Agent service has following features: @@ -54,9 +54,9 @@ Agent service has following features: ### Run Agent -Before running agent we need to provision a client and DATA and CONTROL channel. Client that will be used as gateway representation and make bootstrap configuration. If using Magistrala UI this is done automatically when adding gateway through UI. Gateway can be provisioned with [`provision`][provision] service. +Before running agent we need to provision a client and DATA and CONTROL channel. Client that will be used as gateway representation and make bootstrap configuration. If using Magistrala UI this is done automatically when adding gateway through UI. Gateway can be provisioned with `provision` service. -When you provisioned gateway as described in [provision][provision] you can check results +When you provisioned gateway as described in provision you can check results ```bash curl -s -S -X GET http://magistrala-domain.com:9013/clients/bootstrap/ -H "Authorization: Client " -H 'Content-Type: application/json' |jq @@ -387,7 +387,7 @@ payload := base64.StdEncoding.EncodeToString(b) ### Using configure script -There is a `configuration.sh` script in a `scripts` directory that can be used for automatic configuration and start up of remotely deployed `export`. For this to work it is presumed that `magistrala-export` and `scripts/export_start` are placed in executable path on remote device. Additionally this script requires that remote device is provisioned following the steps described for [provision][provision] service. +There is a `configuration.sh` script in a `scripts` directory that can be used for automatic configuration and start up of remotely deployed `export`. For this to work it is presumed that `magistrala-export` and `scripts/export_start` are placed in executable path on remote device. Additionally this script requires that remote device is provisioned following the steps described for provision service. To run it first edit script to set parameters @@ -406,7 +406,7 @@ MAGISTRALA_USER_PASSWORD='12345678' ### Edge deployment -The following are steps that are an example usage of Magistrala components to connect edge with cloud. We will start Magistrala in the cloud with additional services [Bootstrap][bootstrap] and [Provision][provision]. Using [Bootstrap][bootstrap] and [Provision][provision] we will create a configuration for use in gateway deployment. On the gateway we will start services [Agent][agent] and [Export][export] using previously created configuration. +The following are steps that are an example usage of Magistrala components to connect edge with cloud. We will start Magistrala in the cloud with additional services Bootstrap and Provision. Using Bootstrap and Provision we will create a configuration for use in gateway deployment. On the gateway we will start services [Agent][agent] and [Export][export] using previously created configuration. ## Services in the cloud @@ -583,9 +583,6 @@ magistrala-mqtt | {"level":"info","message":"Publish - client ID export-88529f [agent]: /dev-guide/edge#agent [export]: /dev-guide/edge#export [magistrala]: /dev-guide/architecture -[bootstrap]: /dev-guide/services/bootstrap -[bootstraping]: /dev-guide/services/bootstrap#bootstrapping -[provision]: /dev-guide/services/provision [edgex-repo]: https://github.com/edgexfoundry/edgex-go [conftoml]: https://github.com/absmach/export/blob/master/configs/config.toml [docker-compose]: https://github.com/absmach/magistrala/blob/main/docker/docker-compose.yaml diff --git a/content/docs/dev-guide/extensions/twins.mdx b/content/docs/dev-guide/extensions/twins.mdx index d847c89..424bbc1 100644 --- a/content/docs/dev-guide/extensions/twins.mdx +++ b/content/docs/dev-guide/extensions/twins.mdx @@ -21,7 +21,7 @@ Any data producer or data consumer - which we refer to here collectively as data Although this works well, satisfies the requirements of a wide variety of use cases and corresponds to the intended use of Mainlfux IoT platform, this setup can be insufficient in two important ways. Firstly, different clients, channels, and their connections - i.e. Magistrala representations of different data agent structures - are unrelated to each other, i.e. they do not form a **meaningful whole** and, as a consequence, they do not represent a **single unified system**. Secondly, the **semantic** aspect, i.e. the **meaning** of different clients and channels is not transparent and defined by the sole use of Magistrala platform entities (channels and clients). -Certainly, we can try to describe clients and channels connections and relations as well as their meaning - i.e. their role, position, function in the overall system - by means of their [metadata][provision]. Although this might work well - with a proviso of a lot of additional effort of writing the relatively complex code to create and parse metadata - it is not a practical approach and we still don't get - at least not out of the box - a readable and useful overview of the system as a whole. Also, this approach does not enable us to answer a simple but very important question, i.e. what was the detailed state of a complete system at a certain moment in time. +Certainly, we can try to describe clients and channels connections and relations as well as their meaning - i.e. their role, position, function in the overall system - by means of their metadata. Although this might work well - with a proviso of a lot of additional effort of writing the relatively complex code to create and parse metadata - it is not a practical approach and we still don't get - at least not out of the box - a readable and useful overview of the system as a whole. Also, this approach does not enable us to answer a simple but very important question, i.e. what was the detailed state of a complete system at a certain moment in time. To overcome these problems, Magistrala comes with a **digital twin service**. The twins service is built on top of the Magistrala platform and relies on its architecture and entities, more precisely, on Magistrala users, clients and channels. The primary task of the twin service is to handle Magistrala digital twins. Magistrala digital twin consists of three parts: @@ -39,7 +39,7 @@ You use an HTTP client to communicate with the twins service. Every request sent Twins service listens to the message broker server and intercepts messages passing _via_ the message broker. Every Magistrala message contains information about subchannel and topic used to send a message. Twins service compares this info with attribute definitions of twins persisted in the database, fetches the corresponding twins and updates their respective states. -Before we dwell into twin's anatomy, it is important to realize that in order to use Magistrala twin service, you have to [provision Magistrala clients and channels][provision] and you have to connect clients and channels beforehand. As you go, you can modify your clients, channels and connections and you can modify your digital twin to reflect these modifications, but you have to have at least a minimal setup in order to use the twin service. +Before we dwell into twin's anatomy, it is important to realize that in order to use Magistrala twin service, you have to provision Magistrala clients and channels and you have to connect clients and channels beforehand. As you go, you can modify your clients, channels and connections and you can modify your digital twin to reflect these modifications, but you have to have at least a minimal setup in order to use the twin service. ## Twin's Anatomy @@ -342,7 +342,6 @@ Normally, you can use the default message broker's wildcards. In order to learn Since messages published on message broker are republished on any other protocol supported by Magistrala - HTTP, MQTT, CoAP and WS - you can use any supported protocol client to pick up notifications. [architecture]: /dev-guide/architecture -[provision]: /dev-guide/services/provision [writer]: /dev-guide/dev-tools/storage [senml]: https://tools.ietf.org/html/rfc8428#section-4.3 [authentication]: /dev-guide/dev-tools/authentication diff --git a/content/docs/dev-guide/meta.json b/content/docs/dev-guide/meta.json index 8cbd5eb..2b84ce7 100644 --- a/content/docs/dev-guide/meta.json +++ b/content/docs/dev-guide/meta.json @@ -2,18 +2,18 @@ "title": "Dev Guide", "pages": [ "introduction", - "agent", + "getting-started", "architecture", "storage-architecture", - "getting-started", "entities", "cli", "services", "api", "authorization", "dev-tools", - "edge", "certs", + "agent", + "edge", "extensions" ], "defaultOpen": true diff --git a/content/docs/dev-guide/services/auth.mdx b/content/docs/dev-guide/services/auth.mdx deleted file mode 100644 index f3514d0..0000000 --- a/content/docs/dev-guide/services/auth.mdx +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: Auth -description: Authentication and authorization service for Magistrala — manages API keys, JWT tokens, domains, Personal Access Tokens and SpiceDB-backed fine-grained access control. -keywords: - - Auth - - Authentication - - Authorization - - JWT - - API Keys - - PAT - - SpiceDB - - Domains - - Magistrala -image: /img/mg-preview.png ---- - - - `cmd/auth` still exists and still builds — it's just absent from `docker-compose.yaml`'s default - service list and the Makefile's `SERVICES` — see [Getting Started § Build Individual - Microservice](/dev-guide/getting-started#build-individual-microservice). What's actually gone is - **SpiceDB**: no SpiceDB container exists in `docker-compose.yaml`, and platform-wide identity/ - authorization now runs through Atom, which issues the JWTs/JWKS every other service validates — - see [Architecture § Identity & Access Control](/dev-guide/architecture#identity--access-control). - The Key Types, Domains, and PATs sections below describe `cmd/auth`'s own pre-Atom model and are - kept for historical reference only — for current tokens and workspaces, see - [Architecture](/dev-guide/architecture) and the [API reference](/dev-guide/api). - - -The **Auth service** is the security backbone of Magistrala. It issues and verifies all authentication tokens, manages domains, and enforces fine-grained access control via [SpiceDB](https://authzed.com/spicedb). Every other service delegates authentication and authorization decisions to Auth over gRPC. - -## Key Types - -Auth issues five types of authentication keys, each represented as a signed JWT: - -| Key Type | Description | -| -------------- | -------------------------------------------------------------------------------- | -| Access key | Short-lived token issued on login, used for all API requests | -| Refresh key | Used to obtain a new access key without re-authenticating | -| Recovery key | Short-lived token used during the password reset flow | -| API key | Long-lived, user-created token with configurable expiration; the only revocable type | -| Invitation key | Token used to invite new users to a domain | - -API keys are the only type that can be revoked mid-life. They require a database lookup for each validation because they are not tied to a login session. - -## Domains - -A domain is the top-level organizational unit in Magistrala. Auth manages domain lifecycle and maintains the association between users, their roles within a domain, and the entities (clients, channels, groups) that belong to it. Each domain has a unique `route` used in message routing. - -## Personal Access Tokens (PATs) - -PATs allow API access without primary credentials. They are scoped to specific entity types and operations (e.g., `create` on `clients` in a given domain), expire on a configurable schedule, and can be revoked at any time. Secrets are stored hashed. See [Personal Access Tokens](/user-guide/pats) and the [API reference](/dev-guide/api#personal-access-tokens) for how PATs work today. - -## Configuration - -| Variable | Description | Default | -| :------------------------------- | :----------------------------------------------------------------- | :----------------------------- | -| `MG_AUTH_LOG_LEVEL` | Log level (debug, info, warn, error) | info | -| `MG_AUTH_DB_HOST` | Database host | localhost | -| `MG_AUTH_DB_PORT` | Database port | 5432 | -| `MG_AUTH_DB_USER` | Database user | magistrala | -| `MG_AUTH_DB_PASSWORD` | Database password | magistrala | -| `MG_AUTH_DB_NAME` | Database name | auth | -| `MG_AUTH_DB_SSL_MODE` | SSL mode (disable, require, verify-ca, verify-full) | disable | -| `MG_AUTH_HTTP_HOST` | HTTP host | "" | -| `MG_AUTH_HTTP_PORT` | HTTP port | 8189 | -| `MG_AUTH_GRPC_HOST` | gRPC host | "" | -| `MG_AUTH_GRPC_PORT` | gRPC port | 8181 | -| `MG_AUTH_SECRET_KEY` | Secret for signing tokens | secret | -| `MG_AUTH_ACCESS_TOKEN_DURATION` | Access token TTL | 1h | -| `MG_AUTH_REFRESH_TOKEN_DURATION` | Refresh token TTL | 24h | -| `MG_AUTH_INVITATION_DURATION` | Invitation token TTL | 168h | -| `MG_AUTH_CACHE_URL` | Redis URL for PAT scope cache | redis://localhost:6379/0 | -| `MG_AUTH_CACHE_KEY_DURATION` | PAT scope cache TTL | 10m | -| `MG_SPICEDB_HOST` | SpiceDB host | localhost | -| `MG_SPICEDB_PORT` | SpiceDB port | 50051 | -| `MG_SPICEDB_PRE_SHARED_KEY` | SpiceDB pre-shared key | 12345678 | -| `MG_SPICEDB_SCHEMA_FILE` | Path to SpiceDB schema | ./docker/spicedb/schema.zed | -| `MG_JAEGER_URL` | Jaeger tracing endpoint | http://jaeger:4318/v1/traces | -| `MG_SEND_TELEMETRY` | Send telemetry to Magistrala call-home server | true | -| `MG_CALLOUT_URLS` | Comma-separated callout URLs invoked on authorization checks | "" | -| `MG_CALLOUT_METHOD` | HTTP method for callouts | POST | -| `MG_CALLOUT_TIMEOUT` | Callout timeout | 10s | - -## Deployment - -Auth is distributed as a Docker container. It requires a running PostgreSQL instance, SpiceDB, and (optionally) Redis for PAT caching. - -> **Note:** `auth` is not currently in the Makefile's `SERVICES` list, so `make auth` will fail -> with "No rule to make target". Build it directly with `go build` instead, as shown below. - -```bash -git clone https://github.com/absmach/magistrala -cd magistrala - -go build -o build/auth cmd/auth/main.go -make install - -MG_AUTH_LOG_LEVEL=info \ -MG_AUTH_DB_HOST=localhost \ -MG_AUTH_DB_PORT=5432 \ -MG_AUTH_DB_USER=magistrala \ -MG_AUTH_DB_PASSWORD=magistrala \ -MG_AUTH_DB_NAME=auth \ -MG_AUTH_HTTP_HOST=localhost \ -MG_AUTH_HTTP_PORT=8189 \ -MG_AUTH_GRPC_HOST=localhost \ -MG_AUTH_GRPC_PORT=8181 \ -MG_AUTH_SECRET_KEY=secret \ -MG_SPICEDB_HOST=localhost \ -MG_SPICEDB_PORT=50051 \ -MG_SPICEDB_PRE_SHARED_KEY=12345678 \ -MG_SPICEDB_SCHEMA_FILE=./docker/spicedb/schema.zed \ -$GOBIN/magistrala-auth -``` - -Enable TLS by setting `MG_AUTH_HTTP_SERVER_CERT`/`MG_AUTH_HTTP_SERVER_KEY` for HTTP and `MG_AUTH_GRPC_SERVER_CERT`/`MG_AUTH_GRPC_SERVER_KEY` for gRPC. - -## HTTP API - -Base URL defaults to `http://localhost:8189`. - -### Issue a token (login) - -```bash -curl -X POST http://localhost:9002/users/tokens/issue \ - -H "Content-Type: application/json" \ - -d '{ "identity": "user@example.com", "secret": "password" }' -``` - -### Refresh a token - -```bash -curl -X POST http://localhost:9002/users/tokens/refresh \ - -H "Authorization: Bearer $REFRESH_TOKEN" -``` - -### Health check - -```bash -curl http://localhost:8189/health -``` - -For the full API reference, see the [API documentation](https://docs.api.magistrala.absmach.eu/?urls.primaryName=api%2Fauth.yaml). diff --git a/content/docs/dev-guide/services/channels.mdx b/content/docs/dev-guide/services/channels.mdx deleted file mode 100644 index 36f1663..0000000 --- a/content/docs/dev-guide/services/channels.mdx +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: Channels -description: Channel management service for Magistrala — create and configure communication channels, connect clients, manage access control and route messages between devices and applications. -keywords: - - Channels - - Messaging - - Pub/Sub - - Connections - - Clients - - Access Control - - Magistrala -image: /img/mg-preview.png ---- - - - There is no separate Channels service. Channels are Atom resources of kind `channel`, managed - through Atom's GraphQL API — see [Architecture § Core Concepts](/dev-guide/architecture#core-concepts) - and the CLI's [Channels page](/dev-guide/cli/channels-cli). The content below documents the - pre-Atom architecture and is kept for historical reference only. - - -The **Channels service** manages communication channels in Magistrala. A channel is a message topic that clients connect to for pub/sub messaging. The service handles channel creation, configuration, client connections, group hierarchy, and role-based access control. It exposes both HTTP and gRPC APIs. - -## Configuration - -| Variable | Description | Default | -| ------------------------- | --------------------------------------------------- | ------------------------------ | -| `MG_CHANNELS_LOG_LEVEL` | Log level (debug, info, warn, error) | info | -| `MG_CHANNELS_HTTP_HOST` | HTTP host | localhost | -| `MG_CHANNELS_HTTP_PORT` | HTTP port | 9005 | -| `MG_CHANNELS_GRPC_HOST` | gRPC host | localhost | -| `MG_CHANNELS_GRPC_PORT` | gRPC port | 7005 | -| `MG_CHANNELS_DB_HOST` | Database host | localhost | -| `MG_CHANNELS_DB_PORT` | Database port | 5432 | -| `MG_CHANNELS_DB_USER` | Database user | magistrala | -| `MG_CHANNELS_DB_PASS` | Database password | magistrala | -| `MG_CHANNELS_DB_NAME` | Database name | channels | -| `MG_CHANNELS_DB_SSL_MODE` | SSL mode (disable, require, verify-ca, verify-full) | disable | -| `MG_CHANNELS_CACHE_URL` | Redis cache URL | redis://localhost:6379/0 | -| `MG_JAEGER_URL` | Jaeger tracing endpoint | http://jaeger:4318/v1/traces | -| `MG_SEND_TELEMETRY` | Send telemetry to Magistrala call-home server | true | - -## Database Schema - -### `channels` table - -| Column | Type | Description | -| ----------------- | ------------- | ----------------------------------------------------- | -| `id` | VARCHAR(36) | UUID primary key | -| `name` | VARCHAR(1024) | Human-readable name | -| `domain_id` | VARCHAR(36) | Owning domain | -| `parent_group_id` | VARCHAR(36) | Optional parent group | -| `tags` | TEXT[] | Arbitrary tags | -| `metadata` | JSONB | Free-form structured metadata | -| `status` | SMALLINT | 0 = enabled, 1 = disabled | -| `route` | VARCHAR(36) | Optional unique identifier for routing within a domain | - -### `connections` table - -| Column | Type | Description | -| ------------ | ----------- | ----------------------------------------------- | -| `channel_id` | VARCHAR(36) | Channel UUID | -| `domain_id` | VARCHAR(36) | Domain of channel and client | -| `client_id` | VARCHAR(36) | Client UUID | -| `type` | SMALLINT | 1 = Publish, 2 = Subscribe | - -## Deployment - -```bash -git clone https://github.com/absmach/magistrala -cd magistrala - -make channels -make install - -MG_CHANNELS_LOG_LEVEL=info \ -MG_CHANNELS_HTTP_HOST=localhost \ -MG_CHANNELS_HTTP_PORT=9005 \ -MG_CHANNELS_DB_HOST=localhost \ -MG_CHANNELS_DB_PORT=5432 \ -MG_CHANNELS_DB_USER=magistrala \ -MG_CHANNELS_DB_PASS=magistrala \ -MG_CHANNELS_DB_NAME=channels \ -MG_CHANNELS_CACHE_URL=redis://localhost:6379/0 \ -$GOBIN/magistrala-channels -``` - -## HTTP API - -Base URL defaults to `http://localhost:9005`. All endpoints require `Authorization: Bearer ` and a `` path prefix. - -| Operation | Description | -| ----------------- | ------------------------------------------------- | -| `create` | Create one or more channels | -| `get` | Retrieve a channel by ID | -| `list` | Page and filter channels in a domain | -| `update` | Update name, metadata, tags, or route | -| `delete` | Permanently delete a channel | -| `enable`/`disable`| Toggle channel active state | -| `set-parent` | Assign a parent group | -| `remove-parent` | Detach from parent group | -| `connect` | Connect clients to channels | -| `disconnect` | Remove client-channel connections | -| `create-role` | Create an RBAC role on a channel | -| `add-role-member` | Add users to a channel role | - -### Create a channel - -```bash -curl -X POST "http://localhost:9005//channels" \ - -H "Authorization: Bearer $ACCESS_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "sensor-readings", - "metadata": { "unit": "celsius" }, - "route": "temp-lab", - "tags": ["sensor", "lab"] - }' -``` - -### Connect clients to a channel - -```bash -curl -X POST "http://localhost:9005//channels/connect" \ - -H "Authorization: Bearer $ACCESS_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "channel_ids": [""], - "client_ids": [""], - "types": ["publish", "subscribe"] - }' -``` - -### Disconnect clients from a channel - -```bash -curl -X POST "http://localhost:9005//channels/disconnect" \ - -H "Authorization: Bearer $ACCESS_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "channel_ids": [""], - "client_ids": [""], - "types": ["publish"] - }' -``` - -### Health check - -```bash -curl http://localhost:9005/health -``` - -## Best Practices - -- Use `route` when a channel needs a predictable human-readable identifier for message routing. -- Use tags and metadata to categorize channels by environment, region, or purpose. -- Keep channel hierarchies shallow — avoid deep nesting unless the use case demands it. -- Use `disable` instead of delete when you want to temporarily suspend a channel. -- Regularly audit client-channel connections and remove stale links. -- Grant clients only the connection type they actually need (Publish or Subscribe, not both by default). - -For the full API reference, see the [API documentation](https://docs.api.magistrala.absmach.eu/?urls.primaryName=api%2Fchannels.yaml). diff --git a/content/docs/dev-guide/services/clients.mdx b/content/docs/dev-guide/services/clients.mdx deleted file mode 100644 index 230f398..0000000 --- a/content/docs/dev-guide/services/clients.mdx +++ /dev/null @@ -1,164 +0,0 @@ ---- -title: Clients -description: Client management service for Magistrala — provision devices and applications, manage credentials, connect them to channels, and control access via role-based policies. -keywords: - - Clients - - Devices - - Provisioning - - Credentials - - Channels - - Roles - - Magistrala -image: /img/mg-preview.png ---- - - - There is no separate Clients service. Devices (Magistrala's current public term — see - [Architecture § Core Concepts](/dev-guide/architecture#core-concepts)) are Atom entities of kind - `device`, managed through Atom's GraphQL API — see the CLI's [Devices - page](/dev-guide/cli/devices-cli) and [Gateways page](/dev-guide/cli/gateways-cli). The content - below documents the pre-Atom architecture and is kept for historical reference only. - - -The **Clients service** manages the devices and applications that connect to Magistrala. A client represents any entity that publishes or subscribes to messages. The service handles client provisioning, credential management, channel connections, and role-based access control. It exposes both HTTP and gRPC APIs. - -## Configuration - -| Variable | Description | Default | -| ----------------------------- | ----------------------------------------------------------------------- | ------------------------------ | -| `MG_CLIENTS_LOG_LEVEL` | Log level (debug, info, warn, error) | info | -| `MG_CLIENTS_HTTP_HOST` | HTTP host | localhost | -| `MG_CLIENTS_HTTP_PORT` | HTTP port | 9006 | -| `MG_CLIENTS_GRPC_HOST` | gRPC host | localhost | -| `MG_CLIENTS_GRPC_PORT` | gRPC port | 7000 | -| `MG_CLIENTS_DB_HOST` | Database host | localhost | -| `MG_CLIENTS_DB_PORT` | Database port | 5432 | -| `MG_CLIENTS_DB_USER` | Database user | magistrala | -| `MG_CLIENTS_DB_PASS` | Database password | magistrala | -| `MG_CLIENTS_DB_NAME` | Database name | clients | -| `MG_CLIENTS_DB_SSL_MODE` | SSL mode (disable, require, verify-ca, verify-full) | disable | -| `MG_CLIENTS_CACHE_URL` | Redis cache URL | redis://localhost:6379/0 | -| `MG_CLIENTS_CACHE_KEY_DURATION` | Cache TTL in seconds | 3600 | -| `MG_CLIENTS_ES_URL` | Event store URL | localhost:6379 | -| `MG_AUTH_GRPC_URL` | Auth service gRPC URL | localhost:7001 | -| `MG_AUTH_GRPC_TIMEOUT` | Auth gRPC timeout | 1s | -| `MG_JAEGER_URL` | Jaeger tracing endpoint | http://jaeger:4318/v1/traces | -| `MG_SEND_TELEMETRY` | Send telemetry to Magistrala call-home server | true | - -**Standalone mode**: set `MG_CLIENTS_STANDALONE_ID` and `MG_CLIENTS_STANDALONE_TOKEN` to run without the Auth service (useful for edge deployments). - -## Database Schema - -### `clients` table - -| Column | Type | Description | -| ----------------- | ------------- | -------------------------------------------------- | -| `id` | VARCHAR(36) | UUID primary key | -| `name` | VARCHAR(1024) | Human-readable name | -| `domain_id` | VARCHAR(36) | Owning domain | -| `parent_group_id` | VARCHAR(36) | Optional parent group for hierarchical scoping | -| `identity` | VARCHAR(254) | Login identity | -| `secret` | VARCHAR(4096) | Hashed authentication secret | -| `tags` | TEXT[] | Arbitrary tags | -| `metadata` | JSONB | Free-form structured metadata | -| `status` | SMALLINT | 0 = enabled, 1 = disabled | - -### `connections` table - -| Column | Type | Description | -| ------------ | ----------- | ------------------------------------------------ | -| `channel_id` | VARCHAR(36) | Channel UUID | -| `domain_id` | VARCHAR(36) | Domain of both client and channel | -| `client_id` | VARCHAR(36) | Client UUID | -| `type` | SMALLINT | 1 = Publish, 2 = Subscribe | - -## Deployment - -```bash -git clone https://github.com/absmach/magistrala -cd magistrala - -make clients -make install - -MG_CLIENTS_LOG_LEVEL=info \ -MG_CLIENTS_HTTP_HOST=localhost \ -MG_CLIENTS_HTTP_PORT=9006 \ -MG_CLIENTS_DB_HOST=localhost \ -MG_CLIENTS_DB_PORT=5432 \ -MG_CLIENTS_DB_USER=magistrala \ -MG_CLIENTS_DB_PASS=magistrala \ -MG_CLIENTS_DB_NAME=clients \ -MG_CLIENTS_CACHE_URL=redis://localhost:6379/0 \ -MG_AUTH_GRPC_URL=localhost:7001 \ -$GOBIN/magistrala-clients -``` - -## HTTP API - -Base URL defaults to `http://localhost:9006`. All endpoints require `Authorization: Bearer ` and a `` path prefix. - -| Operation | Description | -| ---------------------- | ---------------------------------------- | -| `create` | Provision one or more clients | -| `get` | Retrieve a client by ID | -| `list` | Page and filter clients in a domain | -| `update` | Update name, metadata, or tags | -| `delete` | Permanently remove a client | -| `enable` / `disable` | Toggle client active state | -| `set-parent-group` | Assign a parent group | -| `remove-parent-group` | Detach from parent group | -| `create-role` | Create an RBAC role for the client | -| `list-roles` | List all roles on a client | -| `add-role-member` | Add users to a client role | - -### Create a client - -```bash -curl -X POST "http://localhost:9006//clients" \ - -H "Authorization: Bearer $ACCESS_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "temperature-sensor-01", - "tags": ["edge", "sensor"], - "metadata": { "model": "DS18B20", "location": "warehouse" } - }' -``` - -### List clients - -```bash -curl "http://localhost:9006//clients?limit=10&status=enabled" \ - -H "Authorization: Bearer $ACCESS_TOKEN" -``` - -### Update a client - -```bash -curl -X PATCH "http://localhost:9006//clients/" \ - -H "Authorization: Bearer $ACCESS_TOKEN" \ - -H "Content-Type: application/json" \ - -d '{ "name": "updated-name", "metadata": { "firmware": "v2.1" } }' -``` - -### Disable a client - -```bash -curl -X POST "http://localhost:9006//clients//disable" \ - -H "Authorization: Bearer $ACCESS_TOKEN" -``` - -### Health check - -```bash -curl http://localhost:9006/health -``` - -## Best Practices - -- Use `metadata` for device attributes (model, firmware version, location) to enable rich filtering. -- Rotate client secrets periodically; use `disable` rather than delete when decommissioning temporarily. -- Prefer standalone mode for edge deployments where the Auth service is not reachable. -- Review client roles and channel connections regularly to audit access. - -For the full API reference, see the [API documentation](https://docs.api.magistrala.absmach.eu/?urls.primaryName=api%2Fclients.yaml). diff --git a/content/docs/dev-guide/services/consumers.mdx b/content/docs/dev-guide/services/consumers.mdx index 613081c..e53da33 100644 --- a/content/docs/dev-guide/services/consumers.mdx +++ b/content/docs/dev-guide/services/consumers.mdx @@ -18,8 +18,7 @@ image: /img/mg-preview.png `cmd/timescale-writer` and `cmd/postgres-writer`. The **Writers** section below is current. The **Notifiers** section (SMTP/SMPP) is not: `consumers/notifiers/*` still exists as source but nothing wires it up to a running service. The current mechanism for the one notification - Magistrala still sends (workspace-invitation emails) is Atom, not this package — see - [Notifications](/dev-guide/services/notifications). + Magistrala still sends (workspace-invitation emails) is Atom, not this package. The **Consumers Service** in Magistrala handles the processing, storage, and notification of messages received from various channels. It is divided into two primary groups: diff --git a/content/docs/dev-guide/services/meta.json b/content/docs/dev-guide/services/meta.json index 53a07bc..4815a60 100644 --- a/content/docs/dev-guide/services/meta.json +++ b/content/docs/dev-guide/services/meta.json @@ -1,17 +1,11 @@ { "title": "Services", "pages": [ - "auth", - "users", - "clients", - "channels", + "bootstrap", "consumers", "readers", - "provision", - "bootstrap", "alarms", "reports", - "rules-engine", - "notifications" + "rules-engine" ] } diff --git a/content/docs/dev-guide/services/notifications.mdx b/content/docs/dev-guide/services/notifications.mdx deleted file mode 100644 index bfe557f..0000000 --- a/content/docs/dev-guide/services/notifications.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Notifications -description: How Magistrala sends workspace-invitation emails today — via Atom's built-in mail sender, not a standalone Magistrala service. -keywords: - - Notifications - - Email - - SMTP - - Invitations - - Atom - - Magistrala -image: /img/mg-preview.png -enterprise: true ---- - - - There is no standalone Notifications service, Users service, or NATS-driven event flow. - Invitation emails are now sent by **Atom** itself, synchronously, as part of handling the - invitation — not by a separate event-driven Magistrala service. - - -When a user is invited to a workspace, Atom renders and sends the invitation email inline — there's no event stream, no gRPC call to a Users service, and nothing for Magistrala to deploy or configure for this to work. The old asynchronous, NATS-driven, cross-service design this page previously described does not exist anymore. - -## How it works - -Atom ships three built-in email templates (verification, password reset, invitation) as `.tmpl` files — a `Subject:` header line, an optional `Content-Type:` header line, a blank line, then a [minijinja](https://docs.rs/minijinja)-templated body. Sending an invitation email calls `mail::send_templated_email` with the `Invitation` template kind and the invitation URL as the single templated variable. - -## Configuration - -Set on Atom, not on any Magistrala service: - -| Variable | Description | -| ---------------------------- | ------------------------------------------------------------------- | -| `ATOM_SMTP_HOST` | SMTP server host — SMTP is considered unconfigured if unset | -| `ATOM_SMTP_FROM` | Sender address | -| `ATOM_SMTP_TLS` | `none`, `tls`, or `starttls` (default) | -| `ATOM_EMAIL_TEMPLATES_DIR` | Directory checked first, one file at a time, before the built-in default — override only the templates you need | -| `ATOM_ALLOW_UNVERIFIED_EMAIL_LOGIN` | Development-only: if SMTP isn't configured, log the invitation URL instead of failing, rather than sending it | - -If SMTP isn't configured and the dev bypass isn't set, sending fails outright rather than silently dropping the email. - -## What's genuinely gone - -- The old event-driven architecture (`domains service → NATS → notifications service → users service gRPC → SMTP`) — replaced by a direct in-process send inside Atom. -- SMPP/SMS notifications, and the generic (non-invitation) SMTP notifier — those lived in Magistrala's own `consumers/notifiers` package, which still exists as source but isn't wired into any running service; see [Consumers § Notifiers](/dev-guide/services/consumers#notifiers). diff --git a/content/docs/dev-guide/services/provision.mdx b/content/docs/dev-guide/services/provision.mdx deleted file mode 100644 index f9c0369..0000000 --- a/content/docs/dev-guide/services/provision.mdx +++ /dev/null @@ -1,677 +0,0 @@ ---- -title: Provision -description: Automate creation of Magistrala entities and edge configurations using the Provision service. -keywords: - - Provision - - Bootstrap - - Clients - - Channels - - Entities - - Automation - - Configuration - - Magistrala -image: /img/mg-preview.png ---- - - - There is no `cmd/provision` directory for the `provision` addon target to build from, and no - `provision` command in the current CLI (see [CLI Introduction](/dev-guide/cli/introduction-to-cli)). - To provision workspaces, devices, and channels today, use - [`workspaces create`](/dev-guide/cli/workspaces-cli), [`devices - create`](/dev-guide/cli/devices-cli), and [`channels create`](/dev-guide/cli/channels-cli) - directly. The content below is kept for historical reference only. - - -Provisioning is a process of configuration of an IoT platform in which system operator creates and sets-up different entities used in the platform - users, groups, channels and clients. - -## Users Management - -### Create an Account - -Use the Magistrala API to create user account: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Content-Type: application/json" https://localhost/users -d '{"first_name": "Jane", "last_name":"Doe","email":"janedoe@example.com", "credentials": {"username": "janedoe", "secret": "12345678"}, "status": "enabled"}' -``` - -Response should look like this: - -```json -HTTP/2 201 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:19:38 GMT -content-type: application/json -content-length: 263 -location: /users/156005cc-df12-4809-aa93-842be168f2ab -access-control-expose-headers: Location - -{"id":"156005cc-df12-4809-aa93-842be168f2ab","first_name":"Jane","last_name":"Doe","status":"enabled","role":"user","credentials":{"username":"janedoe"},"email":"janedoe@example.com","created_at":"2025-02-13T21:19:38.863268Z","updated_at":"0001-01-01T00:00:00Z"} -``` - -Note that when using official `docker-compose`, all services are behind `nginx` proxy and all traffic is `TLS` encrypted. - -### Obtain an Authorization Token - -In order for this user to be able to authenticate to the system, you will have to create an authorization token for them: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Content-Type: application/json" https://localhost/users/tokens/issue -d '{"username":"admin", "password":"12345678"}' -``` - -Response should look like this: - -```json -HTTP/2 201 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:30:06 GMT -content-type: application/json -content-length: 583 -access-control-expose-headers: Location - -{"access_token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzk0ODU4MDYsImlhdCI6MTczOTQ4MjIwNiwiaXNzIjoic3VwZXJtcS5hdXRoIiwidHlwZSI6MCwidXNlciI6IjBkNDA5NDgyLTA3MzctNDVlYS04Mjg0LTViZDg4MDU5ZjYyNSJ9.nFeihdM7KQJKr_2WQaKUFqBGWVw1qfjh0N6Uc5C6UXc2ugtm4LCf0sjDawi9ok_szk0fQeWWX8bqOsnEvhobZA","refresh_token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzk1Njg2MDYsImlhdCI6MTczOTQ4MjIwNiwiaXNzIjoic3VwZXJtcS5hdXRoIiwidHlwZSI6MSwidXNlciI6IjBkNDA5NDgyLTA3MzctNDVlYS04Mjg0LTViZDg4MDU5ZjYyNSJ9.DbaMpgVPtL7ER5wlsFmVtC3izKgjB66qsl1beT0qnlcWcfp7NQyvBtT0EW3OyibcqG56SnqO0ye1mzaJLgViqg"} -``` - -For more information about the Users service API, please check out the [API documentation](https://docs.api.magistrala.absmach.eu/?urls.primaryName=api%2Fhttp.yaml&service=users.yaml). - -## System Provisioning - -Before proceeding, make sure that you have created a new account and obtained an authorization token. You can set your `access_token` in the `USER_TOKEN` environment variable: - -```bash -USER_TOKEN= -``` - -### Provision Clients - -> This endpoint will be depreciated in 1.0.0. It will be replaced with the bulk endpoint currently found at /clients/bulk. - -Clients are created by executing request `POST //clients` with a JSON payload. Note that you will need `user_token` in order to create clients that belong to this particular user. Ensure that you have an active domain. The created client will be part of that domain. - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/clients -d '{"name":"weio"}' -``` - -Response will contain `Location` header whose value represents path to newly created client: - -```json -HTTP/2 201 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:38:46 GMT -content-type: application/json -content-length: 273 -location: /clients/78fbb74b-1a5f-4da2-a15d-3ef18c3cf418 -access-control-expose-headers: Location - -{"id":"78fbb74b-1a5f-4da2-a15d-3ef18c3cf418","name":"weio","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","credentials":{"secret":"3436ee7d-f2a5-4af5-b670-f907918ff442"},"created_at":"2025-02-13T21:38:46.728996Z","updated_at":"0001-01-01T00:00:00Z","status":"enabled"} -``` - -### Bulk Provision Clients - -Multiple clients can be created by executing a `POST /clients/bulk` request with a JSON payload. The payload should contain a JSON array of the clients to be created. If there is an error any of the clients, none of the clients will be created. - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/clients/bulk -d '[{"name":"lightbulb"},{"name":"humidifier"}]' -``` - -The response's body will contain a list of the created clients. - -```json -HTTP/2 200 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:40:56 GMT -content-type: application/json -content-length: 592 -access-control-expose-headers: Location - -{"offset":0,"total":2,"clients":[{"id":"3dee7975-2347-464f-b0c4-baa534d77be4","name":"lightbulb","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","credentials":{"secret":"9e669b34-c73b-4a87-b9b3-1d0e0a2a5594"},"created_at":"2025-02-13T21:40:56.868242Z","updated_at":"0001-01-01T00:00:00Z","status":"enabled"},{"id":"1d441e97-dff8-4db5-b822-3bab0a867284","name":"humidifier","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","credentials":{"secret":"d260dc7d-65ee-43bd-a3ac-ef3a6ecdad6b"},"created_at":"2025-02-13T21:40:56.868245Z","updated_at":"0001-01-01T00:00:00Z","status":"enabled"}]} -``` - -### Retrieve Provisioned Clients - -In order to retrieve data of provisioned clients that are written in database, you can send following request: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/clients -``` - -Notice that you will receive only those clients that were provisioned by `user_token` owner. - -```json -HTTP/2 200 -server: nginx/1.23.3 -date: Tue, 04 Apr 2023 08:42:27 GMT -content-type: application/json -content-length: 570 -access-control-expose-headers: Location - -{ - "limit": 10, - "total": 2, - "clients": [{"id":"3dee7975-2347-464f-b0c4-baa534d77be4","name":"lightbulb","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","credentials":{"secret":"9e669b34-c73b-4a87-b9b3-1d0e0a2a5594"},"created_at":"2025-02-13T21:40:56.868242Z","updated_at":"0001-01-01T00:00:00Z","status":"enabled"}, - {"id":"1d441e97-dff8-4db5-b822-3bab0a867284","name":"humidifier","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","credentials":{"secret":"d260dc7d-65ee-43bd-a3ac-ef3a6ecdad6b"},"created_at":"2025-02-13T21:40:56.868245Z","updated_at":"0001-01-01T00:00:00Z","status":"enabled"} - ] -} -``` - -You can specify `offset` and `limit` parameters in order to fetch a specific subset of clients. In that case, your request should look like: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/clients?offset=0&limit=5 -``` - -You can specify `name` and/or `metadata` parameters in order to fetch specific subset of clients. When specifying metadata you can specify just a part of the metadata JSON you want to match. - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/clients?offset=0&limit=5&name="humidifier" -``` - -```json -HTTP/2 200 -server: nginx/1.23.3 -date: Tue, 04 Apr 2023 08:43:09 GMT -content-type: application/json -content-length: 302 -access-control-expose-headers: Location - -{ - "limit": 5, - "total": 1, - "clients": [ - {"id":"1d441e97-dff8-4db5-b822-3bab0a867284","name":"humidifier","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","credentials":{"secret":"d260dc7d-65ee-43bd-a3ac-ef3a6ecdad6b"},"created_at":"2025-02-13T21:40:56.868245Z","updated_at":"0001-01-01T00:00:00Z","status":"enabled"} - ] -} -``` - -If you don't provide them, default values will be used instead: 0 for `offset` and 10 for `limit`. Note that `limit` cannot be set to values greater than 100. Providing invalid values will be considered malformed request. - -### Disable Clients - -This is a special endpoint that allows you to disable a client, soft deleting it from the database. In order to disable you own client you can send following request: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/clients/1d441e97-dff8-4db5-b822-3bab0a867284/disable -``` - -```json -HTTP/2 200 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:44:57 GMT -content-type: application/json -content-length: 292 -access-control-expose-headers: Location - -{"id":"1d441e97-dff8-4db5-b822-3bab0a867284","name":"humidifier","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","credentials":{},"created_at":"2025-02-13T21:40:56.868245Z","updated_at":"2025-02-13T21:44:57.317573Z","updated_by":"0d409482-0737-45ea-8284-5bd88059f625","status":"disabled"} -``` - -### Enable Clients - -This is a special endpoint that allows you to enable a client that was previously disabled. In order to enable you own client you can send following request: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/clients/1d441e97-dff8-4db5-b822-3bab0a867284/enable -``` - -```json -HTTP/2 200 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:46:48 GMT -content-type: application/json -content-length: 290 -access-control-expose-headers: Location - -{"id":"1d441e97-dff8-4db5-b822-3bab0a867284","name":"humidifier","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","credentials":{},"created_at":"2025-02-13T21:40:56.868245Z","updated_at":"2025-02-13T21:46:48.41145Z","updated_by":"0d409482-0737-45ea-8284-5bd88059f625","status":"enabled"} -``` - -### Provision Channels - -> This endpoint will be depreciated in 1.0.0. It will be replaced with the bulk endpoint currently found at /channels/bulk. - -Channels are created by executing request `POST //channels`: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/channels -d '{"name":"mychan"}' -``` - -After sending request you should receive response with `Location` header that contains path to newly created channel: - -```bash -HTTP/2 201 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:50:55 GMT -content-type: application/json -content-length: 192 -location: /channels/bdf084ff-45ac-4f89-b003-09fe83326238 -access-control-expose-headers: Location - -{"id":"bdf084ff-45ac-4f89-b003-09fe83326238","name":"mychan","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","created_at":"2025-02-13T21:50:55.324198Z","updated_at":"0001-01-01T00:00:00Z"} -``` - -### Bulk Provision Channels - -Multiple channels can be created by executing a `POST //clients/bulk` request with a JSON payload. The payload should contain a JSON array of the channels to be created. If there is an error any of the channels, none of the channels will be created. - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/channels/bulk -d '[{"name":"switch1"},{"name":"truck2"}]' -``` - -The response's body will contain a list of the created channels. - -```json -HTTP/2 200 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:52:02 GMT -content-type: application/json -content-length: 421 -access-control-expose-headers: Location - -{"offset":0,"total":2,"channels":[{"id":"ce56033a-bbce-436a-9d56-bf85ec38f9b3","name":"switch1","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","created_at":"2025-02-13T21:52:02.210708Z","updated_at":"0001-01-01T00:00:00Z"},{"id":"940378c0-da80-4d29-be77-d80482bded70","name":"truck2","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","created_at":"2025-02-13T21:52:02.210709Z","updated_at":"0001-01-01T00:00:00Z"}]} -``` - -### Retrieve Provisioned Channels - -In order to retrieve data of provisioned channels that are written in database, you can send following request: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/channels -``` - -Notice that you will receive only those clients that were provisioned by `user_token` owner. - -```json -HTTP/2 200 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:53:40 GMT -content-type: application/json -content-length: 624 -access-control-expose-headers: Location - -{"limit":10,"offset":0,"total":3,"channels":[{"id":"bdf084ff-45ac-4f89-b003-09fe83326238","name":"mychan","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","created_at":"2025-02-13T21:50:55.324198Z","updated_at":"0001-01-01T00:00:00Z"},{"id":"ce56033a-bbce-436a-9d56-bf85ec38f9b3","name":"switch1","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","created_at":"2025-02-13T21:52:02.210708Z","updated_at":"0001-01-01T00:00:00Z"},{"id":"940378c0-da80-4d29-be77-d80482bded70","name":"truck2","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","created_at":"2025-02-13T21:52:02.210709Z","updated_at":"0001-01-01T00:00:00Z"}]} -``` - -You can specify `offset` and `limit` parameters in order to fetch specific subset of channels. In that case, your request should look like: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/channels?offset=0&limit=5 -``` - -If you don't provide them, default values will be used instead: 0 for `offset` and 10 for `limit`. Note that `limit` cannot be set to values greater than 100. Providing invalid values will be considered malformed request. - -### Disable Channels - -This is a special endpoint that allows you to disable a channel, soft deleting it from the database. In order to disable you own channel you can send following request: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/channels/bdf084ff-45ac-4f89-b003-09fe83326238/disable -``` - -```json -HTTP/2 200 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:55:14 GMT -content-type: application/json -content-length: 271 -access-control-expose-headers: Location - -{"id":"bdf084ff-45ac-4f89-b003-09fe83326238","name":"mychan","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","created_at":"2025-02-13T21:50:55.324198Z","updated_at":"2025-02-13T21:55:14.577701Z","updated_by":"0d409482-0737-45ea-8284-5bd88059f625","status":"disabled"} -``` - -### Enable Channels - -This is a special endpoint that allows you to enable a channel that was previously disabled. In order to enable you own channel you can send following request: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X POST -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/channels/bdf084ff-45ac-4f89-b003-09fe83326238/enable -``` - -```json -HTTP/2 200 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 21:56:56 GMT -content-type: application/json -content-length: 251 -access-control-expose-headers: Location - -{"id":"bdf084ff-45ac-4f89-b003-09fe83326238","name":"mychan","domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516","created_at":"2025-02-13T21:50:55.324198Z","updated_at":"2025-02-13T21:56:56.255417Z","updated_by":"0d409482-0737-45ea-8284-5bd88059f625"} -``` - -## Access Control - -Channel can be observed as a communication group of clients. Only clients that are connected to the channel can send and receive messages from other clients in this channel. Clients that are not connected to this channel are not allowed to communicate over it. Users may also be assigned to channels, thus sharing clients between users. With the necessary policies in place, users can be granted access to clients that are not owned by them. - -A user who is the owner of a channel or a user that has been assigned to the channel with the required policy can connect clients to the channel. This is equivalent of giving permissions to these clients to communicate over given communication group. - -To connect a client to the channel you should send following request: - -> This endpoint will be depreciated in 1.0.0. It will be replaced with the bulk endpoint found at /connect. - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X PUT -H "Authorization: Bearer $USER_TOKEN" https://localhost//channels//connect -d '{ - "client_ids": ["client_id"], - "types": ["publish"] -}' -``` - -For example: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X PUT -H "Authorization: Bearer $USER_TOKEN" https://localhost/cd992e16-f2b2-4f85-90c5-39bd7fc3e516/channels/bdf084ff-45ac-4f89-b003-09fe83326238/connect -d '{"client_ids": ["78fbb74b-1a5f-4da2-a15d-3ef18c3cf418"], "types": ["publish"]}' -``` - -```json -HTTP/2 405 -server: nginx/1.25.4 -date: Thu, 13 Feb 2025 22:12:13 GMT -content-length: 0 -allow: POST - -``` - -You can observe which clients are connected to specific channel: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -H "Authorization: Bearer $USER_TOKEN" https://localhost//channels//clients -``` - -You can observe to which channels is specified client connected: - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -H "Authorization: Bearer $USER_TOKEN" https://localhost/clients//channels -``` - -If you want to disconnect your client from the channel, send following request: - -> This endpoint will be depreciated in 1.0.0. It will be replaced with the bulk endpoint found at /disconnect. - -```bash -curl -s -S -i --cacert docker/ssl/certs/ca.crt -X DELETE -H "Authorization: Bearer $USER_TOKEN" https://localhost//channels//disconnect -d '{"client_ids": ["78fbb74b-1a5f-4da2-a15d-3ef18c3cf418"], "types": ["publish"]}' -``` - -Response that you'll get should look like this: - -```json -HTTP/2 204 -server: nginx/1.23.3 -date: Tue, 04 Apr 2023 09:57:53 GMT -access-control-expose-headers: Location -``` - -For more information about the Clients service API, please check out the [API documentation](https://docs.api.magistrala.absmach.eu/?urls.primaryName=api%2Fhttp.yaml&service=clients.yaml). - -## Provision Service - -Provisioning is a process of configuration of an IoT platform in which system operator creates and sets-up different entities used in the platform - users, channels and clients. It is part of process of setting up IoT applications where we connect devices on edge with platform in cloud. For provisioning we can use [Magistrala CLI][cli] for creating users and for each node in the edge (eg. gateway) required number of clients, channels, connecting them and creating certificates if needed. Provision service is used to set up initial application configuration once user is created. Provision service creates clients, channels, connections and certificates. Once user is created we can use provision to create a setup for edge node in one HTTP request instead of issuing several CLI commands. - -Provision service provides an HTTP API to interact with [Magistrala][provision-api]. - -For gateways to communicate with [Magistrala][magistrala] configuration is required (MQTT host, client, channels, certificates...). Gateway will send a request to [Bootstrap][bootstrap] service providing `` and `` in HTTP request to get the configuration. To make a request to [Bootstrap][bootstrap] service you can use [Agent][agent] service on a gateway. - -To create bootstrap configuration you can use [Bootstrap][bootstrap] or `Provision` service. Magistrala UI uses [Bootstrap][bootstrap] service for creating gateway configurations. `Provision` service should provide an easy way of provisioning your gateways i.e creating bootstrap configuration and as many clients and channels that your setup requires. - -Also, you may use provision service to create certificates for each client. Each service running on gateway may require more than one client and channel for communication. -If, for example, you are using services [Agent][agent] and Export on a gateway you will need two channels for `Agent` (`data` and `control`) and one client for `Export`. -Additionally, if you enabled mTLS each service will need its own client and certificate for access to [Magistrala][magistrala]. -Your setup could require any number of clients and channels, this kind of setup we can call `provision layout`. - -Provision service provides a way of specifying this `provision layout` and creating a setup according to that layout by serving requests on `/mapping` endpoint. Provision layout is configured in [config.toml][conftoml]. - -### Configuration - -The service is configured using the environment variables presented in the following [table][config]. Note that any unset variables will be replaced with their default values. - -By default, call to `/mapping` endpoint will create one client and two channels (`control` and `data`) and connect it as this is typical setup required by [Agent](/dev-guide/edge#agent). If there is a requirement for different provision layout we can use [config][conftoml] file in addition to environment variables. - -For the purposes of running provision as an add-on in docker composition environment variables seems more suitable. Environment variables are set in [.env][env]. - -Configuration can be specified in [config.toml][conftoml]. Config file can specify all the settings that environment variables can configure and in addition `/mapping` endpoint provision layout can be configured. - -In `config.toml` we can enlist an array of clients and channels that we want to create and make connections between them which we call provision layout. - -Clients Metadata can be whatever suits your needs. Client that has metadata with `external_id` will have bootstrap configuration created, `external_id` value will be populated with value from [request](#example)). -Bootstrap configuration can be fetched with [Agent][agent]. For channel's metadata `type` is reserved for `control` and `data` which we use with [Agent][agent]. - -Example of provision layout below - -```toml -[bootstrap] - [bootstrap.content] - [bootstrap.content.agent.edgex] - url = "http://localhost:48090/api/v1/" - - [bootstrap.content.agent.log] - level = "info" - - [bootstrap.content.agent.mqtt] - mtls = false - qos = 0 - retain = false - skip_tls_ver = true - url = "localhost:1883" - - [bootstrap.content.agent.server] - nats_url = "localhost:4222" - port = "9000" - - [bootstrap.content.agent.heartbeat] - interval = "30s" - - [bootstrap.content.agent.terminal] - session_timeout = "30s" - - [bootstrap.content.export.exp] - log_level = "debug" - nats = "nats://localhost:4222" - port = "8172" - cache_url = "localhost:6379" - cache_pass = "" - cache_db = "0" - - [bootstrap.content.export.mqtt] - ca_path = "ca.crt" - cert_path = "client.crt" - channel = "" - host = "tcp://localhost:1883" - mtls = false - password = "" - priv_key_path = "client.key" - qos = 0 - retain = false - skip_tls_ver = false - username = "" - - [[bootstrap.content.export.routes]] - mqtt_topic = "" - nats_topic = "channels" - subtopic = "" - type = "mfx" - workers = 10 - - [[bootstrap.content.export.routes]] - mqtt_topic = "" - nats_topic = "export" - subtopic = "" - type = "default" - workers = 10 - -[[clients]] - name = "client" - - [clients.metadata] - external_id = "xxxxxx" - -[[channels]] - name = "control-channel" - - [channels.metadata] - type = "control" - -[[channels]] - name = "data-channel" - - [channels.metadata] - type = "data" - -[[channels]] - name = "export-channel" - - [channels.metadata] - type = "export" -``` - -`[bootstrap.content]` will be marshalled and saved into `content` field in bootstrap configs when request to `/mappings` is made, `content` field from bootstrap config is used to create `Agent` and `Export` configuration files upon `Agent` fetching bootstrap configuration. - -### Authentication - -In order to create necessary entities provision service needs to authenticate against Magistrala. -To provide authentication credentials to the provision service you can pass them in as environment variables, in a config file as Magistrala user credentials, or as an API token issued on the `/users/tokens/issue` endpoint of the [users service][users]. - -Additionally, users or API token can be passed in Authorization header, this authentication takes precedence over others. - -- `username`, `password` - (`MG_PROVISION_USER`, `MG_PROVISION_PASSWORD` in [.env][env], `MG_user`, `MG_pass` in [config.toml][conftoml]) -- API Key - (`MG_PROVISION_API_KEY` in [.env][env] or [config.toml][conftoml]) -- `Authorization: Bearer Token|ApiKey` - request authorization header containing users token. Check [auth][auth]. - -### Running - -Provision service can be run as a standalone or in docker composition as addon to the core docker composition. - -Standalone: - -```bash -MG_PROVISION_BS_SVC_URL=http://bootstrap:9013 \ -MG_PROVISION_CLIENTS_LOCATION=http://clients:9006 \ -MG_PROVISION_USERS_LOCATION=http://users:9002 \ -MG_PROVISION_CONFIG_FILE=/configs/config.toml \ -build/magistrala-provision -``` - -Docker composition: - -```bash -docker-compose -f docker/addons/provision/docker-compose.yml up -``` - -### Provision - -For the case that credentials or API token is passed in configuration file or environment variables, call to `/mapping` endpoint doesn't require `Authentication` header: - -```bash -curl -s -S -X POST http://localhost:9016/mapping -H 'Content-Type: application/json' -d '{"external_id": "33:52:77:99:43", "external_key": "223334fw2"}' -``` - -In the case that provision service is not deployed with credentials or API key or you want to use user other than one being set in environment (or config file): - -```bash -curl -s -S -X POST http://localhost:9016/mapping -H "Authorization: Bearer " -H 'Content-Type: application/json' -d '{"external_id": "", "external_key": ""}' -``` - -Or if you want to specify a name for client different than in `config.toml` you can specify post data as: - -```json -{ - "name": "", - "external_id": "", - "external_key": "" -} -``` - -Response contains created clients, channels and certificates if any: - -```json -{ - "clients": [ - { - "id": "c22b0c0f-8c03-40da-a06b-37ed3a72c8d1", - "name": "client", - "domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516", - "credentials":{"secret":"9e669b34-c73b-4a87-b9b3-1d0e0a2a5594"}, - "metadata": { - "external_id": "33:52:79:C3:43" - } - } - ], - "channels": [ - { - "id": "064c680e-181b-4b58-975e-6983313a5170", - "domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516", - "name": "control-channel", - "metadata": { - "type": "control" - } - }, - { - "id": "579da92d-6078-4801-a18a-dd1cfa2aa44f", - "domain_id":"cd992e16-f2b2-4f85-90c5-39bd7fc3e516", - "name": "data-channel", - "metadata": { - "type": "data" - } - } - ], - "whitelisted": { - "c22b0c0f-8c03-40da-a06b-37ed3a72c8d1": true - } -} -``` - -### Example - -Deploy Magistrala UI docker composition as it contains all the required services for provisioning to work ( `certs`, `bootstrap` and Magistrala core) - -```bash -git clone https://github.com/absmach/magistrala-ui -cd magistrala-ui -docker-compose -f docker/docker-compose.yml up -``` - -Create user and obtain access token - -```bash -magistrala-cli users create john.doe@email.com 12345678 - -# Retrieve token -magistrala-cli users token john.doe@email.com 12345678 - -created: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTY1ODU3MDUsImlhdCI6MTU5NjU0OTcwNSwiaXNzIjoibWFpbmZsdXguYXV0aG4iLCJzdWIiOiJtaXJrYXNoQGdtYWlsLmNvbSIsInR5cGUiOjB9._vq0zJzFc9tQqc8x74kpn7dXYefUtG9IB0Cb-X2KMK8 -``` - -Put a value of token into environment variable - -```bash -TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTY1ODU3MDUsImlhdCI6MTU5NjU0OTcwNSwiaXNzIjoibWFpbmZsdXguYXV0aG4iLCJzdWIiOiJtaXJrYXNoQGdtYWlsLmNvbSIsInR5cGUiOjB9._vq0zJzFc9tQqc8x74kpn7dXYefUtG9IB0Cb-X2KMK8 -``` - -Make a call to provision endpoint - -```bash -curl -s -S -X POST http://magistrala.com:9016/mapping -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{"name":"edge-gw", "external_id" : "gateway", "external_key":"external_key" }' -``` - -To check the results you can make a call to bootstrap endpoint - -```bash -curl -s -S -X GET http://magistrala.com:9013/clients/bootstrap/gateway -H "Authorization: Client external_key" -H 'Content-Type: application/json' -``` - -Or you can start `Agent` with: - -```bash -git clone https://github.com/absmach/agent.git -cd agent -make -MG_AGENT_BOOTSTRAP_ID=gateway MG_AGENT_BOOTSTRAP_KEY=external_key MG_AGENT_BOOTSTRAP_URL=http://magistrala.ccom:9013/clients/bootstrap build/magistrala-agent -``` - -Agent will retrieve connections parameters and connect to Magistrala cloud. - -For more information about the Provision service, please check out the [service source and implementation][provision-api]. - -[magistrala]: https://github.com/absmach/magistrala -[bootstrap]: /dev-guide/services/bootstrap -[agent]: https://github.com/absmach/agent -[config]: https://github.com/absmach/magistrala/tree/main/provision#configuration -[env]: https://github.com/absmach/magistrala/blob/main/docker/.env -[conftoml]: https://github.com/absmach/magistrala/blob/main/docker/addons/provision/configs/config.toml -[users]: /dev-guide/services/users -[cli]: /dev-guide/cli/introduction-to-cli -[auth]: /dev-guide/dev-tools/authentication -[provision-api]: https://github.com/absmach/magistrala/tree/main/provision diff --git a/content/docs/dev-guide/services/users.mdx b/content/docs/dev-guide/services/users.mdx deleted file mode 100644 index cb6a1ce..0000000 --- a/content/docs/dev-guide/services/users.mdx +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: Users -description: User management service for Magistrala — handles registration, login, profile management, password reset, email verification and account lifecycle. -keywords: - - Users - - Registration - - Authentication - - Profile - - Password Reset - - Email Verification - - Magistrala -image: /img/mg-preview.png ---- - - - There is no separate Users service (or Auth service) in the current deployment. User accounts - are now Atom entities of kind `human`, and authentication goes through Atom directly - (`magistrala-cli login`) — see [Architecture § Core Concepts](/dev-guide/architecture#core-concepts) - for the current model. The content below documents the pre-Atom architecture and is kept for - historical reference only. - - -The **Users service** provides an HTTP API for managing user accounts on the Magistrala platform. It handles registration, login, profile updates, password reset, email verification, and account lifecycle (enable/disable/delete). It communicates with the Auth service over gRPC for token issuance and validation. - -## Configuration - -| Variable | Description | Default | -| ---------------------------------- | ----------------------------------------------------------------------- | --------------------------------- | -| `MG_USERS_LOG_LEVEL` | Log level (debug, info, warn, error) | info | -| `MG_USERS_ADMIN_EMAIL` | Default admin account created on startup | admin@example.com | -| `MG_USERS_ADMIN_PASSWORD` | Default admin password | 12345678 | -| `MG_USERS_PASS_REGEX` | Password validation regex | `^.{8,}$` | -| `MG_USERS_HTTP_HOST` | HTTP host | localhost | -| `MG_USERS_HTTP_PORT` | HTTP port | 9002 | -| `MG_USERS_DB_HOST` | Database host | localhost | -| `MG_USERS_DB_PORT` | Database port | 5432 | -| `MG_USERS_DB_USER` | Database user | magistrala | -| `MG_USERS_DB_PASS` | Database password | magistrala | -| `MG_USERS_DB_NAME` | Database name | users | -| `MG_USERS_DB_SSL_MODE` | SSL mode (disable, require, verify-ca, verify-full) | disable | -| `MG_AUTH_GRPC_URL` | Auth service gRPC URL | localhost:8181 | -| `MG_AUTH_GRPC_TIMEOUT` | Auth service gRPC timeout | 1s | -| `MG_EMAIL_HOST` | SMTP server host | localhost | -| `MG_EMAIL_PORT` | SMTP server port | 25 | -| `MG_EMAIL_USERNAME` | SMTP username | "" | -| `MG_EMAIL_PASSWORD` | SMTP password | "" | -| `MG_EMAIL_FROM_ADDRESS` | Sender email address | "" | -| `MG_EMAIL_FROM_NAME` | Sender display name | "" | -| `MG_PASSWORD_RESET_URL_PREFIX` | URL prefix for password reset links | http://localhost/password/reset | -| `MG_VERIFICATION_URL_PREFIX` | URL prefix for email verification links | http://localhost/verify-email | -| `MG_USERS_ES_URL` | Event store URL | nats://localhost:4222 | -| `MG_USERS_DELETE_INTERVAL` | Interval for running the account deletion sweep | 24h | -| `MG_USERS_DELETE_AFTER` | Grace period before a disabled account is permanently deleted | 720h | -| `MG_JAEGER_URL` | Jaeger tracing endpoint | http://localhost:4318/v1/traces | -| `MG_SEND_TELEMETRY` | Send telemetry to Magistrala call-home server | true | - -## Deployment - -```bash -git clone https://github.com/absmach/magistrala -cd magistrala - -make users -make install - -MG_USERS_LOG_LEVEL=info \ -MG_USERS_ADMIN_EMAIL=admin@example.com \ -MG_USERS_ADMIN_PASSWORD=12345678 \ -MG_USERS_HTTP_HOST=localhost \ -MG_USERS_HTTP_PORT=9002 \ -MG_USERS_DB_HOST=localhost \ -MG_USERS_DB_PORT=5432 \ -MG_USERS_DB_USER=magistrala \ -MG_USERS_DB_PASS=magistrala \ -MG_USERS_DB_NAME=users \ -MG_AUTH_GRPC_URL=localhost:8181 \ -MG_EMAIL_HOST=smtp.example.com \ -MG_EMAIL_PORT=587 \ -MG_EMAIL_FROM_ADDRESS=noreply@example.com \ -$GOBIN/magistrala-users -``` - -Set `MG_USERS_HTTP_SERVER_CERT` and `MG_USERS_HTTP_SERVER_KEY` to enable TLS. If `MG_EMAIL_HOST` is not reachable, the service still starts but password reset emails will not be sent. - -## HTTP API - -Base URL defaults to `http://localhost:9002`. - -| Operation | Description | -| --------------- | --------------------------------------------------------- | -| Register | Create a user account | -| Issue token | Exchange credentials for access/refresh tokens (login) | -| Refresh token | Obtain a new access token using a refresh token | -| Profile | Fetch the authenticated user's own profile | -| View user | Retrieve a user by ID | -| List users | Page and filter users | -| Update user | Patch name, metadata, tags, profile picture | -| Change identity | Update email or username | -| Change secret | Update password | -| Enable/Disable | Activate or deactivate an account | -| Delete | Permanently remove an account | -| Verify email | Confirm email address via link | -| Password reset | Request and apply a password reset | - -### Register a user - -```bash -curl -X POST http://localhost:9002/users \ - -H "Content-Type: application/json" \ - -d '{ - "first_name": "Ada", - "last_name": "Lovelace", - "credentials": { "username": "ada", "secret": "changeMe123" }, - "email": "ada@example.com" - }' -``` - -### Login - -```bash -curl -X POST http://localhost:9002/users/tokens/issue \ - -H "Content-Type: application/json" \ - -d '{ "identity": "ada@example.com", "secret": "changeMe123" }' -``` - -### View own profile - -```bash -curl http://localhost:9002/users/profile \ - -H "Authorization: Bearer $ACCESS_TOKEN" -``` - -### List users - -```bash -curl "http://localhost:9002/users?limit=10&status=enabled" \ - -H "Authorization: Bearer $ACCESS_TOKEN" -``` - -### Request password reset - -```bash -curl -X POST http://localhost:9002/password/reset-request \ - -H "Content-Type: application/json" \ - -d '{ "email": "ada@example.com" }' -``` - -### Health check - -```bash -curl http://localhost:9002/health -``` - -## Best Practices - -- Disable self-registration in production and onboard users via admin tokens. -- Require email verification before granting domain roles (`MG_ALLOW_UNVERIFIED_USER=false`). -- Harden passwords with `MG_USERS_PASS_REGEX` and enforce rotation. -- Use `MG_USERS_DELETE_AFTER` to automatically purge stale disabled accounts. -- Store SMTP credentials in a secrets manager, not in image environment. - -For the full API reference, see the [API documentation](https://docs.api.magistrala.absmach.eu/?urls.primaryName=api%2Fusers.yaml).