feat: add v1 API node action endpoints#2585
Conversation
|
@tanrax can you resolve the conflicts here ? |
Add POST endpoints under /api/v1/actions/ for interacting with
mesh nodes via Bearer token authentication:
- POST /api/v1/actions/traceroute
- POST /api/v1/actions/request-position
- POST /api/v1/actions/request-nodeinfo
- POST /api/v1/actions/request-neighbors
These mirror the existing internal API endpoints but are
accessible with API token auth, enabling external clients
(CLI tools, Emacs, scripts) to trigger node actions without
session cookies or CSRF tokens.
All endpoints accept destination as nodeId ("!a1b2c3d4"),
nodeNum (number), or hex string. They respect the same
permissions and rate limits as the internal API.
01a42e9 to
44b7cf2
Compare
The middleware sets req.user (not req.apiTokenUser), and hasPermission is async and takes a User object, not user.permissions. Both bugs caused TypeError crashes on any request to /api/v1/actions/*.
|
@Yeraze Of course! I resolved the conflicts and ran the tests |
Code ReviewOverviewAdds four POST endpoints under Critical Issues1. Uses the deprecated singleton
|
- Use resolveSourceManager instead of deprecated meshtasticManager singleton - Scope rate-limit map key to sourceId to prevent cross-source leakage - Add pruneNeighborRateLimit to prevent unbounded map growth - Fix message ID format to canonical sourceId_nodeNum_packetId - Pass sourceId as second arg to insertMessage for proper per-source storage - Fix resolveDestination to reject null/undefined with == null check - Add consistent channel override support to all four action endpoints - Move actionsRouter mount to per-source path /sources/:sourceId/actions - Add comprehensive handler tests covering auth, permissions, rate-limiting, destination validation, source isolation, and canonical ID format
|
Done! Can you check now please? |
The actions router was the only per-source v1 mount that hand-rolled the 401/hasPermission checks instead of delegating to the `attachSource` middleware every other resource uses. Practical fallout: - `/sources/default/actions/*` did not resolve the `default` alias and fell back to the legacy singleton — the exact thing the original review item Yeraze#1 was meant to prevent. - Permission checks were duplicated inline four times. - `req.source` was never populated, so handlers couldn't read the canonical Source row. This switches to per-route `attachSource(resource, action)` so the endpoint can keep its split between `traceroute:write` and `messages:write` while reusing the same source-resolution + per-source 403 machinery as the rest of v1. Handlers drop the inline auth blocks and read `req.params.sourceId` after attachSource canonicalises it. Tests gain mocks for `databaseService.sources.{getSource,getAllSources}`, update the 403 body assertions to the attachSource response shape (`required: { resource, action, sourceId }`), and add coverage for the `default` alias 200 / 404 paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Pushed a follow-up refactor (
All 47 actions tests pass locally; CI is running. Take a look when you have a moment — feel free to revert the commit if you'd prefer to land your version as-is and tackle this as a follow-up PR. |
Summary
Add POST endpoints under
/api/v1/actions/for interacting with mesh nodes via Bearer token authentication:POST /api/v1/actions/traceroute- Send traceroute to a nodePOST /api/v1/actions/request-position- Request position from a nodePOST /api/v1/actions/request-nodeinfo- Request node info exchange (key exchange for DMs)POST /api/v1/actions/request-neighbors- Request neighbor info (local/0-hop nodes only)Motivation
The internal API (
/api/traceroute,/api/position/request, etc.) requires session cookies + CSRF tokens, making it inaccessible to external API clients that use Bearer token authentication.This is needed for tools like meshmonitor-chat.el (Emacs client) and any CLI/script that uses the v1 API with tokens.
Details
destinationas nodeId ("!a1b2c3d4"), nodeNum (number), or hex stringRequest body
{ "destination": "!a1b2c3d4" }Or alternatively:
{ "nodeId": "!a1b2c3d4" }or{ "nodeNum": 48596172 }Test plan