kopia lustrzana https://github.com/Yakifo/amqtt
Merge pull request #281 from ajmirsky/plugin_docs
Expanded structure for plugin documentationpull/284/head
commit
cdcee7cbf8
|
@ -129,7 +129,9 @@ class Broker:
|
|||
plugin_namespace: plugin namespace to use when loading plugin entry_points. defaults to `amqtt.broker.plugins`.
|
||||
|
||||
Raises:
|
||||
BrokerError, ParserError, PluginError
|
||||
BrokerError: problem with broker configuration
|
||||
PluginImportError: if importing a plugin from configuration
|
||||
PluginInitError: if initialization plugin fails
|
||||
|
||||
"""
|
||||
|
||||
|
|
|
@ -86,7 +86,8 @@ class MQTTClient:
|
|||
config: dictionary of configuration options (see [client configuration](client_config.md)).
|
||||
|
||||
Raises:
|
||||
PluginError
|
||||
PluginImportError: if importing a plugin from configuration
|
||||
PluginInitError: if initialization plugin fails
|
||||
|
||||
"""
|
||||
|
||||
|
@ -145,7 +146,7 @@ class MQTTClient:
|
|||
[CONNACK](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718033)'s return code
|
||||
|
||||
Raises:
|
||||
ClientError, ConnectError
|
||||
ConnectError: could not connect to broker
|
||||
|
||||
"""
|
||||
additional_headers = additional_headers if additional_headers is not None else {}
|
||||
|
@ -380,6 +381,7 @@ class MQTTClient:
|
|||
|
||||
Raises:
|
||||
asyncio.TimeoutError: if timeout occurs before a message is delivered
|
||||
ClientError: if client is not connected
|
||||
|
||||
"""
|
||||
if self._handler is None:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import logging
|
||||
from dataclasses import dataclass, field, fields, replace
|
||||
import logging
|
||||
|
||||
try:
|
||||
from enum import Enum, StrEnum
|
||||
|
@ -9,15 +9,14 @@ except ImportError:
|
|||
class StrEnum(str, Enum): #type: ignore[no-redef]
|
||||
pass
|
||||
|
||||
from pathlib import Path
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any, Literal
|
||||
|
||||
from dacite import Config as DaciteConfig, from_dict as dict_to_dataclass
|
||||
|
||||
from amqtt.mqtt.constants import QOS_0, QOS_2
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import asyncio
|
||||
|
||||
|
@ -155,9 +154,9 @@ class BrokerConfig(Dictable):
|
|||
listeners: dict[Literal["default"] | str, ListenerConfig] = field(default_factory=default_listeners) # noqa: PYI051
|
||||
"""Network of listeners used by the services. a 'default' named listener is required; if another listener
|
||||
does not set a value, the 'default' settings are applied. See
|
||||
[ListenerConfig](./#amqtt.contexts.ListenerConfig) for more information."""
|
||||
[ListenerConfig](#amqtt.contexts.ListenerConfig) for more information."""
|
||||
sys_interval: int | None = None
|
||||
"""*Deprecated field to configure the `BrokerSysPlugin`. See [`BrokerSysPlugin`](../packaged_plugins.md/#sys-topics)
|
||||
"""*Deprecated field to configure the `BrokerSysPlugin`. See [`BrokerSysPlugin`](#sys-topics)
|
||||
for recommended configuration.*"""
|
||||
timeout_disconnect_delay: int | None = 0
|
||||
"""Client disconnect timeout without a keep-alive."""
|
||||
|
@ -165,8 +164,8 @@ class BrokerConfig(Dictable):
|
|||
"""Seconds for an inactive session to be retained."""
|
||||
auth: dict[str, Any] | None = None
|
||||
"""*Deprecated field used to config EntryPoint-loaded plugins. See
|
||||
[`AnonymousAuthPlugin`](./#anonymous-auth-plugin) and
|
||||
[`FileAuthPlugin`](/packaged_plugins/#password-file-auth-plugin) for recommended configuration.*"""
|
||||
[`AnonymousAuthPlugin`](#anonymous-auth-plugin) and
|
||||
[`FileAuthPlugin`](#password-file-auth-plugin) for recommended configuration.*"""
|
||||
topic_check: dict[str, Any] | None = None
|
||||
"""*Deprecated field used to config EntryPoint-loaded plugins. See
|
||||
[`TopicTabooPlugin`](#taboo-topic-plugin) and
|
||||
|
@ -328,7 +327,7 @@ class ClientConfig(Dictable):
|
|||
"""Specify the topics and what flags should be set for messages published to them."""
|
||||
broker: ConnectionConfig | None = field(default_factory=ConnectionConfig)
|
||||
"""Configuration for connecting to the broker. See
|
||||
[ConnectionConfig](./#amqtt.contexts.ConnectionConfig) for more information."""
|
||||
[ConnectionConfig](#amqtt.contexts.ConnectionConfig) for more information."""
|
||||
plugins: dict[str, Any] | list[dict[str, Any]] | None = field(default_factory=default_client_plugins)
|
||||
"""The dictionary has a key of the dotted-module path of a class derived from `BasePlugin`; the value is
|
||||
a dictionary of configuration options for that plugin. See [Plugins](http://localhost:8000/custom_plugins/)
|
||||
|
@ -337,7 +336,7 @@ class ClientConfig(Dictable):
|
|||
"""If establishing a secure connection, should the hostname of the certificate be verified."""
|
||||
will: WillConfig | None = None
|
||||
"""Message, topic and flags that should be sent to if the client disconnects. See
|
||||
[WillConfig](./#amqtt.contexts.WillConfig)"""
|
||||
[WillConfig](#amqtt.contexts.WillConfig)"""
|
||||
|
||||
def __post__init__(self) -> None:
|
||||
"""Check config for errors and transform fields for easier use."""
|
||||
|
|
|
@ -56,14 +56,15 @@ class UserAuthDBPlugin(BaseAuthPlugin, BaseTopicPlugin):
|
|||
|
||||
connection: str
|
||||
"""SQLAlchemy connection string for the asyncio version of the database connector:
|
||||
- mysql+aiomysql://user:password@host:port/dbname
|
||||
- postgresql+asyncpg://user:password@host:port/dbname
|
||||
- sqlite+aiosqlite:///dbfilename.db
|
||||
|
||||
- `mysql+aiomysql://user:password@host:port/dbname`
|
||||
- `postgresql+asyncpg://user:password@host:port/dbname`
|
||||
- `sqlite+aiosqlite:///dbfilename.db`
|
||||
"""
|
||||
sync_schema: bool = False
|
||||
"""Use SQLAlchemy to create / update the database schema."""
|
||||
hash_schemes: list[str] = field(default_factory=default_hash_scheme)
|
||||
|
||||
"""list of hash schemes to use for passwords"""
|
||||
|
||||
class TopicAuthDBPlugin(BaseTopicPlugin):
|
||||
|
||||
|
@ -100,9 +101,10 @@ class TopicAuthDBPlugin(BaseTopicPlugin):
|
|||
|
||||
connection: str
|
||||
"""SQLAlchemy connection string for the asyncio version of the database connector:
|
||||
- mysql+aiomysql://user:password@host:port/dbname
|
||||
- postgresql+asyncpg://user:password@host:port/dbname
|
||||
- sqlite+aiosqlite:///dbfilename.db
|
||||
|
||||
- `mysql+aiomysql://user:password@host:port/dbname`
|
||||
- `postgresql+asyncpg://user:password@host:port/dbname`
|
||||
- `sqlite+aiosqlite:///dbfilename.db`
|
||||
"""
|
||||
sync_schema: bool = False
|
||||
"""Use SQLAlchemy to create / update the database schema."""
|
||||
|
|
|
@ -48,7 +48,7 @@ HTTP_4xx_MIN = 400
|
|||
HTTP_4xx_MAX = 499
|
||||
|
||||
|
||||
class HttpAuthTopicPlugin(BaseAuthPlugin, BaseTopicPlugin):
|
||||
class HttpAuthPlugin(BaseAuthPlugin, BaseTopicPlugin):
|
||||
|
||||
def __init__(self, context: BrokerContext) -> None:
|
||||
super().__init__(context)
|
||||
|
@ -137,44 +137,27 @@ class HttpAuthTopicPlugin(BaseAuthPlugin, BaseTopicPlugin):
|
|||
|
||||
@dataclass
|
||||
class Config:
|
||||
"""Configuration for the HTTP Auth & ACL Plugin.
|
||||
|
||||
Members:
|
||||
- host *(str) hostname of the server for the auth & acl check
|
||||
- port *(int) port of the server for the auth & acl check
|
||||
- user_uri *(str) uri of the topic check (e.g. '/user')
|
||||
- topic_uri *(str) uri of the topic check (e.g. '/acl')
|
||||
- request_method *(RequestMethod) send the request as a GET, POST or PUT
|
||||
- params_mode *(ParamsMode) send the request with json or form data
|
||||
- response_mode *(ResponseMode) expected response from the auth/acl server. STATUS (code), JSON, or TEXT.
|
||||
- user_agent *(str) the 'User-Agent' header sent along with the request
|
||||
|
||||
ParamsMode:
|
||||
|
||||
for user authentication, the http server will receive in json or form format the following:
|
||||
- username *(str)*
|
||||
- password *(str)*
|
||||
- client_id *(str)*
|
||||
|
||||
for superuser validation, the http server will receive in json or form format the following:
|
||||
- username *(str)*
|
||||
|
||||
for acl check, the http server will receive in json or form format the following:
|
||||
- username *(str)*
|
||||
- client_id *(str)*
|
||||
- topic *(str)*
|
||||
- acc *(int)* client can receive (1), can publish(2), can receive & publish (3) and can subscribe (4)
|
||||
"""
|
||||
"""Configuration for the HTTP Auth & ACL Plugin."""
|
||||
|
||||
host: str
|
||||
"""hostname of the server for the auth & acl check"""
|
||||
port: int
|
||||
"""port of the server for the auth & acl check"""
|
||||
user_uri: str
|
||||
"""URI of the topic check (e.g. '/user')"""
|
||||
topic_uri: str
|
||||
"""URI of the topic check (e.g. '/acl')"""
|
||||
request_method: RequestMethod = RequestMethod.GET
|
||||
params_mode: ParamsMode = ParamsMode.JSON
|
||||
response_mode: ResponseMode = ResponseMode.JSON
|
||||
"""send the request as a GET, POST or PUT"""
|
||||
params_mode: ParamsMode = ParamsMode.JSON # see docs/plugins/http.md for additional details
|
||||
"""send the request with `JSON` or `FORM` data. *additional details below*"""
|
||||
response_mode: ResponseMode = ResponseMode.JSON # see docs/plugins/http.md for additional details
|
||||
"""expected response from the auth/acl server. `STATUS` (code), `JSON`, or `TEXT`. *additional details below*"""
|
||||
with_tls: bool = False
|
||||
"""http or https"""
|
||||
user_agent: str = "amqtt"
|
||||
|
||||
"""the 'User-Agent' header sent along with the request"""
|
||||
superuser_uri: str | None = None
|
||||
"""URI to verify if the user is a superuser (e.g. '/superuser'), `None` if superuser is not supported"""
|
||||
timeout: int = 5
|
||||
"""duration, in seconds, to wait for the HTTP server to respond"""
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
# Contributed Plugins
|
||||
|
||||
Plugins that are not part of the core functionality of the aMQTT broker or client and require additional dependencies:
|
||||
|
||||
`$ pip install '.[contrib]'`
|
||||
|
||||
# Relational Database for Authentication and Authorization
|
||||
|
||||
- `amqtt.contrib.auth_db.AuthUserDBPlugin` (authentication) verify a client's ability to connect to broker
|
||||
- `amqtt.contrib.auth_db.AuthTopicDBPlugine` (authorization) determine a client's access to topics
|
||||
|
||||
Relational database access is supported using SQLAlchemy so MySQL, MariaDB, Postgres and SQLite support is available.
|
||||
|
||||
For ease of use, the [`user_mgr` command-line utility](contrib_plugins.md/#user_mgr) to add, remove, update and
|
||||
list clients. And the [`topic_mgr` command-line utility](contrib_plugins.md/#user_topic) to add client access to
|
||||
subscribe, publish and receive messages on topics.
|
||||
|
||||
## Authentication Configuration
|
||||
|
||||
::: amqtt.contrib.auth_db.UserAuthDBPlugin.Config
|
||||
|
||||
## Authorization Configuration
|
||||
|
||||
::: amqtt.contrib.auth_db.TopicAuthDBPlugin.Config
|
||||
|
||||
## Command line for authentication
|
||||
|
||||
::: mkdocs-typer2
|
||||
:module: amqtt.contrib.auth_db.user_mgr_cli
|
||||
:name: user_mgr
|
||||
|
||||
## Command line for authorization
|
||||
|
||||
::: mkdocs-typer2
|
||||
:module: amqtt.contrib.auth_db.topic_mgr_cli
|
||||
:name: topic_mgr
|
||||
|
||||
# Authentication & Topic Access via external HTTP server
|
||||
|
||||
`amqtt.contrib.http.HttpAuthTopicPlugin`
|
||||
|
||||
If clients accessing the broker are managed by another application, implement API endpoints
|
||||
that allows the broker to check if a client is authenticated and what topics that client
|
||||
is authorized to access.
|
||||
|
||||
**Configuration**
|
||||
|
||||
- `host` *(str) hostname of the server for the auth & acl check
|
||||
- `port` *(int) port of the server for the auth & acl check
|
||||
- `user_uri` *(str) uri of the user auth check (e.g. '/user')
|
||||
- `topic_uri` *(str) uri of the topic check (e.g. '/acl')
|
||||
- `request_method` *(RequestMethod) send the request as a GET, POST or PUT
|
||||
- `params_mode` *(ParamsMode) send the request with json or form data
|
||||
- `response_mode` *(ResponseMode) expected response from the auth/acl server. STATUS (code), JSON, or TEXT.
|
||||
- `user_agent` *(str) the 'User-Agent' header sent along with the request
|
||||
|
||||
Each endpoint (uri) will receive the information needed to determine authentication and authorization (in either
|
||||
json or form data format, based on the `params_mode`)
|
||||
|
||||
For user authentication (`user_uri`), the http server will receive in json or form format the following:
|
||||
- username *(str)*
|
||||
- password *(str)*
|
||||
- client_id *(str)*
|
||||
|
||||
For superuser validation (`superuser_uri`), the http server will receive in json or form format the following:
|
||||
- username *(str)*
|
||||
|
||||
For acl check (`acl_uri`), the http server will receive in json or form format the following:
|
||||
- username *(str)*
|
||||
- client_id *(str)*
|
||||
- topic *(str)*
|
||||
- acc *(int)* client can receive (1), can publish(2), can receive & publish (3) and can subscribe (4)
|
||||
|
||||
|
||||
The HTTP endpoints can respond in three different ways, depending on `response_mode`:
|
||||
|
||||
1. STATUS - allowing access should respond with a 2xx status code. rejection is 4xx.
|
||||
if a 5xx is received, the plugin will not participate in the filtering operation and will defer to another topic filtering plugin to determine access
|
||||
2. JSON - response should be `{'ok':true|false|null, 'error':'optional reason for false or null response'}`.
|
||||
`true` allows access, `false` denies access and `null` the plugin will not participate in the filtering operation
|
||||
3. TEXT - `ok` allows access, any other message denies access. non-participation not supported with this mode.
|
|
@ -0,0 +1,39 @@
|
|||
# Relational Database for Authentication and Authorization
|
||||
|
||||
- `amqtt.contrib.auth_db.AuthUserDBPlugin` (authentication) verify a client's ability to connect to broker
|
||||
- `amqtt.contrib.auth_db.AuthTopicDBPlugin` (authorization) determine a client's access to topics
|
||||
|
||||
Relational database access is supported using SQLAlchemy so MySQL, MariaDB, Postgres and SQLite support is available.
|
||||
|
||||
For ease of use, the [`user_mgr` command-line utility](auth_db.md/#user_mgr) to add, remove, update and
|
||||
list clients. And the [`topic_mgr` command-line utility](auth_db.md/#topic_mgr) to add client access to
|
||||
subscribe, publish and receive messages on topics.
|
||||
|
||||
## Authentication Configuration
|
||||
|
||||
::: amqtt.contrib.auth_db.UserAuthDBPlugin.Config
|
||||
options:
|
||||
heading_level: 4
|
||||
extra:
|
||||
class_style: "simple"
|
||||
|
||||
## Authorization Configuration
|
||||
|
||||
::: amqtt.contrib.auth_db.TopicAuthDBPlugin.Config
|
||||
options:
|
||||
heading_level: 4
|
||||
extra:
|
||||
class_style: "simple"
|
||||
|
||||
## CLI
|
||||
|
||||
|
||||
::: mkdocs-typer2
|
||||
:module: amqtt.contrib.auth_db.user_mgr_cli
|
||||
:name: user_mgr
|
||||
|
||||
|
||||
::: mkdocs-typer2
|
||||
:module: amqtt.contrib.auth_db.topic_mgr_cli
|
||||
:name: topic_mgr
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# Contributed Plugins
|
||||
|
||||
These are fully supported plugins but require additional dependencies to be installed:
|
||||
|
||||
`$ pip install '.[contrib]'`
|
||||
|
||||
|
||||
- Relational Database Auth<br/>
|
||||
_includes manager script to add, remove and create db entries_
|
||||
- [DB Client Authentication](auth_db.md)<br/>
|
||||
Authenticate a client's connection to broker based on entries in a relational db (mysql, postgres, maria, sqlite).<br/>
|
||||
`amqtt.contrib.auth_db.AuthUserDBPlugin`
|
||||
- [DB Client Authorization](auth_db.md)<br/>
|
||||
Determine a client's access to topics.<br/>
|
||||
`amqtt.contrib.auth_db.AuthTopicDBPlugin`
|
||||
|
||||
- [HTTP Auth](http.md)<br/>
|
||||
Determine client authentication and authorization based on response from a separate HTTP server.<br/>
|
||||
`amqtt.contrib.http.HttpAuthTopicPlugin`
|
|
@ -77,7 +77,9 @@ and then run via `amqtt -c myBroker.yaml`.
|
|||
variables to configure its behavior.
|
||||
|
||||
::: amqtt.plugins.base.BasePlugin
|
||||
|
||||
options:
|
||||
show_source: false
|
||||
heading_level: 3
|
||||
|
||||
|
||||
## Events
|
||||
|
@ -85,16 +87,13 @@ and then run via `amqtt -c myBroker.yaml`.
|
|||
|
||||
All plugins are notified of events if the `BasePlugin` subclass implements one or more of these methods:
|
||||
|
||||
### Client and Broker
|
||||
|
||||
### Client
|
||||
|
||||
- `async def on_mqtt_packet_sent(self, *, packet: MQTTPacket[MQTTVariableHeader, MQTTPayload[MQTTVariableHeader], MQTTFixedHeader], session: Session | None = None) -> None`
|
||||
- `async def on_mqtt_packet_received(self, *, packet: MQTTPacket[MQTTVariableHeader, MQTTPayload[MQTTVariableHeader], MQTTFixedHeader], session: Session | None = None) -> None`
|
||||
|
||||
### Client Only
|
||||
|
||||
none
|
||||
|
||||
### Broker Only
|
||||
### Broker
|
||||
|
||||
- `async def on_broker_pre_start(self) -> None`
|
||||
- `async def on_broker_post_start(self) -> None`
|
||||
|
@ -111,6 +110,9 @@ none
|
|||
- `async def on_broker_client_unsubscribed(self, *, client_id: str, topic: str) -> None`
|
||||
|
||||
- `async def on_broker_message_received(self, *, client_id: str, message: ApplicationMessage) -> None`
|
||||
- `async def on_broker_message_broadcast(self, *, client_id: str, message: ApplicationMessage) -> None`
|
||||
- `async def on_mqtt_packet_sent(self, *, packet: MQTTPacket[MQTTVariableHeader, MQTTPayload[MQTTVariableHeader], MQTTFixedHeader], session: Session | None = None) -> None`
|
||||
- `async def on_mqtt_packet_received(self, *, packet: MQTTPacket[MQTTVariableHeader, MQTTPayload[MQTTVariableHeader], MQTTFixedHeader], session: Session | None = None) -> None`
|
||||
|
||||
|
||||
## Authentication Plugins
|
||||
|
@ -128,6 +130,9 @@ If there are multiple authentication plugins:
|
|||
- `None` gets ignored from the determination
|
||||
|
||||
::: amqtt.plugins.base.BaseAuthPlugin
|
||||
options:
|
||||
show_source: false
|
||||
heading_level: 3
|
||||
|
||||
## Topic Filter Plugins
|
||||
|
||||
|
@ -144,7 +149,9 @@ If there are multiple topic plugins:
|
|||
- `None` will be ignored
|
||||
|
||||
::: amqtt.plugins.base.BaseTopicPlugin
|
||||
|
||||
options:
|
||||
show_source: false
|
||||
heading_level: 3
|
||||
|
||||
!!! note
|
||||
A custom plugin class can subclass from both `BaseAuthPlugin` and `BaseTopicPlugin` as long it defines
|
|
@ -0,0 +1,97 @@
|
|||
# Authentication & Authorization via external HTTP server
|
||||
|
||||
`amqtt.contrib.http.HttpAuthPlugin`
|
||||
|
||||
If clients accessing the broker are managed by another application, it can implement API endpoints
|
||||
that respond with information about client authenticated and topic-level authorization.
|
||||
|
||||
!!! info "browser-based mqtt over websockets"
|
||||
|
||||
One of the primary use cases for this plugin is to enable browser-based applications to communicate with mqtt
|
||||
over websockets.
|
||||
|
||||
!!! warning
|
||||
Care must be taken to make sure the mqtt password is secure (encrypted).
|
||||
|
||||
For more implementation information:
|
||||
|
||||
??? info "recipe for authentication"
|
||||
Provide the client id and username when webpage is initially rendered or passed to the mqtt initialization from stored
|
||||
cookies. If application is secure, the user's password will be hashed should be encrypted and cannot be used to
|
||||
authenticate a client. Instead, the application should create an encrypted password (eg jwt) which the server
|
||||
can then verify when the broker contacts the application.
|
||||
|
||||
??? example "mqtt in javascript"
|
||||
Example initialization of mqtt in javascript:
|
||||
|
||||
import mqtt from 'mqtt';
|
||||
const url = 'https://path.to.amqtt.broker';
|
||||
const options = {
|
||||
'myclientid',
|
||||
connectTimeout: 30000,
|
||||
username: 'myclientid',
|
||||
password: '' // encrypted password
|
||||
};
|
||||
try {
|
||||
const clientMqtt = await mqtt.connect(url, options);
|
||||
|
||||
See the 'Request and Response Modes' section below for details on `params_mode` and `response_mode`.
|
||||
|
||||
::: amqtt.contrib.http.HttpAuthPlugin.Config
|
||||
options:
|
||||
show_source: false
|
||||
heading_level: 4
|
||||
extra:
|
||||
class_style: "simple"
|
||||
|
||||
[//]: # (manually creating the heading so it doesn't show in the sidebar ToC)
|
||||
<h2>Params and Response Modes</h2>
|
||||
|
||||
Each URI endpoint will receive different information in order to determine authentication and authorization;
|
||||
format will depend on `params_mode` configuration attribute (`json` or `form`).:
|
||||
|
||||
*For user authentication, the request will contain:*
|
||||
|
||||
- username *(str)*
|
||||
- password *(str)*
|
||||
- client_id *(str)*
|
||||
|
||||
*For superuser validation, the request will contain:*
|
||||
|
||||
- username *(str)*
|
||||
|
||||
*For acl check, the request will contain:*
|
||||
|
||||
- username *(str)*
|
||||
- client_id *(str)*
|
||||
- topic *(str)*
|
||||
- acc *(int)* : client can receive (1), can publish(2), can receive & publish (3) and can subscribe (4)
|
||||
|
||||
All endpoints should respond with the following, dependent on `response_mode` configuration attribute:
|
||||
|
||||
*In `status` mode:
|
||||
|
||||
- status code: 2xx (granted) or 4xx(denied) or 5xx (noop)
|
||||
|
||||
!!! note "5xx response"
|
||||
**noop** (no operation): plugin will not participate in the filtering operation and will defer to another
|
||||
topic filtering plugin to determine access. if there is no other topic filtering plugin, access will be denied.
|
||||
|
||||
*In `json` mode:*
|
||||
|
||||
- status code: 2xx
|
||||
- content-type: application/json
|
||||
- response: {'ok': True } (granted), {'ok': False, 'error': 'optional error message' } (denied) or { 'error': 'optional error message' } (noop)
|
||||
|
||||
!!! note "excluded 'ok' key"
|
||||
**noop** (no operation): plugin will not participate in the filtering operation and will defer to another
|
||||
topic filtering plugin to determine access. if there is no other topic filtering plugin, access will be denied.
|
||||
|
||||
*In `text` mode:*
|
||||
|
||||
- status code: 2xx
|
||||
- content-type: text/plain
|
||||
- response: 'ok' or 'error'
|
||||
|
||||
!!! note "noop not supported"
|
||||
in text mode, noop (no operation) is not supported
|
|
@ -23,7 +23,7 @@ and configured for the broker:
|
|||
--8<-- "pyproject.toml:included"
|
||||
```
|
||||
|
||||
But the same 4 plugins were activated in the previous default config:
|
||||
But the previous default config only caused 4 plugins to be active:
|
||||
|
||||
```yaml
|
||||
--8<-- "samples/legacy.yaml"
|
||||
|
@ -248,7 +248,7 @@ plugins:
|
|||
|
||||
`amqtt.plugins.logging_amqtt.PacketLoggerPlugin`
|
||||
|
||||
This plugin issues debug-level messages for [mqtt events](custom_plugins.md#client-and-broker): `on_mqtt_packet_sent`
|
||||
This plugin issues debug-level messages for [mqtt events](custom_plugins.md#events): `on_mqtt_packet_sent`
|
||||
and `on_mqtt_packet_received`.
|
||||
|
||||
```yaml
|
|
@ -32,4 +32,5 @@ used by the included broker script: [broker configuration](broker_config.md)
|
|||
|
||||
::: amqtt.broker.Broker
|
||||
|
||||
|
||||
[^1]: See [PyYAML](http://pyyaml.org/wiki/PyYAMLDocumentation) for loading YAML files as Python dict.
|
||||
|
|
|
@ -10,11 +10,13 @@ from _griffe.agents.visitor import Visitor
|
|||
from _griffe.models import Attribute
|
||||
|
||||
from amqtt.contexts import default_listeners, default_broker_plugins, default_client_plugins
|
||||
from amqtt.contrib.auth_db.plugin import default_hash_scheme
|
||||
|
||||
default_factory_map = {
|
||||
'default_listeners': default_listeners(),
|
||||
'default_broker_plugins': default_broker_plugins(),
|
||||
'default_client_plugins': default_client_plugins()
|
||||
'default_client_plugins': default_client_plugins(),
|
||||
'default_hash_scheme': default_hash_scheme()
|
||||
}
|
||||
|
||||
def get_qualified_name(node: ast.AST) -> str | None:
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
template overrides for mkdocs-materials
|
|
@ -38,9 +38,12 @@ nav:
|
|||
- Client: references/client.md
|
||||
- Common: references/common.md
|
||||
- Plugins:
|
||||
- Packaged: packaged_plugins.md
|
||||
- Custom: custom_plugins.md
|
||||
- Contributed: contrib_plugins.md
|
||||
- Packaged: plugins/packaged_plugins.md
|
||||
- Custom: plugins/custom_plugins.md
|
||||
- Contributed:
|
||||
- plugins/contrib.md
|
||||
- Database Auth: plugins/auth_db.md
|
||||
- HTTP Auth: plugins/http.md
|
||||
- Configuration:
|
||||
- Broker: references/broker_config.md
|
||||
- Client: references/client_config.md
|
||||
|
@ -58,6 +61,7 @@ theme:
|
|||
name: material
|
||||
logo: assets/amqtt_bw.svg
|
||||
features:
|
||||
- toc.integrate
|
||||
- announce.dismiss
|
||||
- content.action.edit
|
||||
- content.action.view
|
||||
|
@ -118,6 +122,7 @@ markdown_extensions:
|
|||
- pymdownx.tilde
|
||||
- toc:
|
||||
permalink: "¤"
|
||||
toc_depth: 3
|
||||
|
||||
plugins:
|
||||
- search
|
||||
|
@ -135,7 +140,6 @@ plugins:
|
|||
options:
|
||||
# extra:
|
||||
# template_log_display: true
|
||||
annotation_path: "full"
|
||||
docstring_options:
|
||||
ignore_init_summary: true
|
||||
docstring_section_style: list
|
||||
|
|
|
@ -8,7 +8,7 @@ from aiohttp.web import Response
|
|||
|
||||
from amqtt.broker import BrokerContext, Broker
|
||||
from amqtt.contexts import Action
|
||||
from amqtt.contrib.http import HttpAuthTopicPlugin, ParamsMode, ResponseMode, RequestMethod
|
||||
from amqtt.contrib.http import HttpAuthPlugin, ParamsMode, ResponseMode, RequestMethod
|
||||
from amqtt.session import Session
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -135,7 +135,7 @@ async def test_request_acl_response(empty_broker, http_server, kind, url,
|
|||
username, matcher, is_allowed):
|
||||
|
||||
context = BrokerContext(broker=empty_broker)
|
||||
context.config = HttpAuthTopicPlugin.Config(
|
||||
context.config = HttpAuthPlugin.Config(
|
||||
host="127.0.0.1",
|
||||
port=8080,
|
||||
user_uri=url,
|
||||
|
@ -144,7 +144,7 @@ async def test_request_acl_response(empty_broker, http_server, kind, url,
|
|||
params_mode=params_mode,
|
||||
response_mode=response_mode,
|
||||
)
|
||||
http_acl = HttpAuthTopicPlugin(context)
|
||||
http_acl = HttpAuthPlugin(context)
|
||||
logger.warning(f'kind is {kind}')
|
||||
if kind == TestKind.ACL:
|
||||
s = Session()
|
||||
|
|
Ładowanie…
Reference in New Issue