🚧 WIP
This commit is contained in:
+152
-1
@@ -18,7 +18,10 @@ from app.deps import CurrentUser, require_roles
|
||||
from app.dynsec import DynsecError, dynsec_client
|
||||
from app.models import ManagementRole, MqttClientMetadata
|
||||
from app.schemas import (
|
||||
ClientRoleAssign,
|
||||
GroupIn,
|
||||
GroupMemberAssign,
|
||||
GroupRoleAssign,
|
||||
MqttClientCreate,
|
||||
MqttClientOut,
|
||||
MqttPasswordReset,
|
||||
@@ -39,12 +42,13 @@ def _metadata(db: Session, username: str) -> MqttClientMetadata | None:
|
||||
|
||||
def _client_out(db: Session, client: dict) -> MqttClientOut:
|
||||
meta = _metadata(db, client.get("username", ""))
|
||||
# dynsec reports `disabled` (absent == enabled); the API exposes `enabled`.
|
||||
return MqttClientOut(
|
||||
username=client.get("username", ""),
|
||||
clientid=client.get("clientid") or None,
|
||||
text_name=client.get("textname"),
|
||||
text_description=client.get("textdescription"),
|
||||
enabled=client.get("enabled", False),
|
||||
enabled=not client.get("disabled", False),
|
||||
groups=client.get("groups", []),
|
||||
roles=client.get("roles", []),
|
||||
owner=meta.owner if meta else None,
|
||||
@@ -181,6 +185,55 @@ def reset_password(
|
||||
return MqttPasswordReset(username=username, password=password)
|
||||
|
||||
|
||||
@router.post("/clients/{username}/roles", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def assign_client_role(
|
||||
username: str,
|
||||
body: ClientRoleAssign,
|
||||
request: Request,
|
||||
db: DbDep,
|
||||
_user: BrokerAdmin,
|
||||
):
|
||||
"""Add one role to an existing client (incremental, spec section 11)."""
|
||||
try:
|
||||
dynsec_client.add_client_role(username, body.rolename, body.priority)
|
||||
except DynsecError as exc:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, str(exc)) from exc
|
||||
audit.record(
|
||||
db,
|
||||
"CLIENT_ROLE_ADDED",
|
||||
request=request,
|
||||
object_type="mqtt_client",
|
||||
object_id=username,
|
||||
new_value={"rolename": body.rolename, "priority": body.priority},
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/clients/{username}/roles/{rolename}", status_code=status.HTTP_204_NO_CONTENT
|
||||
)
|
||||
def unassign_client_role(
|
||||
username: str,
|
||||
rolename: str,
|
||||
request: Request,
|
||||
db: DbDep,
|
||||
_user: BrokerAdmin,
|
||||
):
|
||||
try:
|
||||
dynsec_client.remove_client_role(username, rolename)
|
||||
except DynsecError as exc:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, str(exc)) from exc
|
||||
audit.record(
|
||||
db,
|
||||
"CLIENT_ROLE_REMOVED",
|
||||
request=request,
|
||||
object_type="mqtt_client",
|
||||
object_id=username,
|
||||
old_value={"rolename": rolename},
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
# --- Groups ------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -228,6 +281,104 @@ def delete_group(
|
||||
return None
|
||||
|
||||
|
||||
@router.post("/groups/{groupname}/clients", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def add_group_member(
|
||||
groupname: str,
|
||||
body: GroupMemberAssign,
|
||||
request: Request,
|
||||
db: DbDep,
|
||||
_user: BrokerAdmin,
|
||||
):
|
||||
"""Add one client to a group (spec section 12)."""
|
||||
try:
|
||||
dynsec_client.add_group_client(groupname, body.username, body.priority)
|
||||
except DynsecError as exc:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, str(exc)) from exc
|
||||
audit.record(
|
||||
db,
|
||||
"GROUP_MEMBER_ADDED",
|
||||
request=request,
|
||||
object_type="mqtt_group",
|
||||
object_id=groupname,
|
||||
new_value={"username": body.username, "priority": body.priority},
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/groups/{groupname}/clients/{username}", status_code=status.HTTP_204_NO_CONTENT
|
||||
)
|
||||
def remove_group_member(
|
||||
groupname: str,
|
||||
username: str,
|
||||
request: Request,
|
||||
db: DbDep,
|
||||
_user: BrokerAdmin,
|
||||
):
|
||||
try:
|
||||
dynsec_client.remove_group_client(groupname, username)
|
||||
except DynsecError as exc:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, str(exc)) from exc
|
||||
audit.record(
|
||||
db,
|
||||
"GROUP_MEMBER_REMOVED",
|
||||
request=request,
|
||||
object_type="mqtt_group",
|
||||
object_id=groupname,
|
||||
old_value={"username": username},
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
@router.post("/groups/{groupname}/roles", status_code=status.HTTP_204_NO_CONTENT)
|
||||
def assign_group_role(
|
||||
groupname: str,
|
||||
body: GroupRoleAssign,
|
||||
request: Request,
|
||||
db: DbDep,
|
||||
_user: BrokerAdmin,
|
||||
):
|
||||
"""Add one role to a group (spec section 12)."""
|
||||
try:
|
||||
dynsec_client.add_group_role(groupname, body.rolename, body.priority)
|
||||
except DynsecError as exc:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, str(exc)) from exc
|
||||
audit.record(
|
||||
db,
|
||||
"GROUP_ROLE_ADDED",
|
||||
request=request,
|
||||
object_type="mqtt_group",
|
||||
object_id=groupname,
|
||||
new_value={"rolename": body.rolename, "priority": body.priority},
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/groups/{groupname}/roles/{rolename}", status_code=status.HTTP_204_NO_CONTENT
|
||||
)
|
||||
def unassign_group_role(
|
||||
groupname: str,
|
||||
rolename: str,
|
||||
request: Request,
|
||||
db: DbDep,
|
||||
_user: BrokerAdmin,
|
||||
):
|
||||
try:
|
||||
dynsec_client.remove_group_role(groupname, rolename)
|
||||
except DynsecError as exc:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, str(exc)) from exc
|
||||
audit.record(
|
||||
db,
|
||||
"GROUP_ROLE_REMOVED",
|
||||
request=request,
|
||||
object_type="mqtt_group",
|
||||
object_id=groupname,
|
||||
old_value={"rolename": rolename},
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
@router.get("/roles")
|
||||
def list_roles(_user: BrokerAdmin):
|
||||
return dynsec_client.list_roles()
|
||||
|
||||
Reference in New Issue
Block a user