mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
feat(filters): JSONPath field filters, operators, AST groups, fragments, and test-match
Add a field filter type reading any payload value by JSONPath with array expansion, 12 comparison operators (eq/ne/contains/startsWith/endsWith/regex/gt/gte/lt/lte/in/exists), a visual AST builder (all/any/not) in the route editor, chip-based multi-value input, a stateless POST /admin/api/test-match dry-run, and named filter fragments stored in D1 (d1_fragments, migration 0010) inlined into route ASTs on insert.
This commit is contained in:
parent
c955db03c3
commit
c090281cb2
30 changed files with 1793 additions and 422 deletions
|
|
@ -19,6 +19,8 @@ The console itself is served at `/admin`; its tabs are deep-linkable via the URL
|
|||
| `PUT /admin/api/groups` | Replace groups (super: all; owner: own only) |
|
||||
| `GET /admin/api/groups/:id/routes` | List a group's routes |
|
||||
| `PUT /admin/api/groups/:id/routes` | Replace a group's routes (owner/admin) |
|
||||
| `GET /admin/api/groups/:id/fragments` | List a group's named filter fragments |
|
||||
| `PUT /admin/api/groups/:id/fragments` | Replace a group's named filter fragments (owner/admin) |
|
||||
| `PUT /admin/api/groups/:id/rename` | Rename a group (owner); routes, webhook secret and invites follow |
|
||||
| `GET /admin/api/groups/:id/invites` | List pending invites (owner) |
|
||||
| `POST /admin/api/groups/:id/invites` | Create an invite link (owner) |
|
||||
|
|
@ -31,11 +33,14 @@ The console itself is served at `/admin`; its tabs are deep-linkable via the URL
|
|||
| `GET /admin/api/audit` | Audit log (scoped to accessible groups) |
|
||||
| `GET /admin/api/metrics` | Delivery stats (totals, failure rate, per platform/event/status, recent failures); optional `?groupId=` scope; recent failures scoped to accessible groups for non-super |
|
||||
| `GET /admin/api/delivery/:deliveryId` | All send-log attempts for one delivery (group-scoped) |
|
||||
| `POST /admin/api/test-match` | Stateless filter dry-run — evaluate a filter node against a pasted JSON payload (no event is stored) |
|
||||
|
||||
## Validation
|
||||
|
||||
- `PUT /admin/api/routes` — Body `{ "routes": Route[] }`; validates each route (id pattern, unique id within its group, name, enabled, `groupId`, filters — empty only allowed for `fallback` routes — optional `discordRoleIds` (list of role id strings), and platform-aware targets: `target.channelId` for Discord, `target.chatId` for Telegram) and persists to D1 `d1_routes`. Returns `200 { ok, count }` or `400 { error }` / `401 { error }` / `403 { error }`. Unchanged routes skip the full validation.
|
||||
- `PUT /admin/api/routes` — Body `{ "routes": Route[] }`; validates each route (id pattern, unique id within its group, name, enabled, `groupId`, filters — empty only allowed for `fallback` routes — optional `discordRoleIds` (list of role id strings), and platform-aware targets: `target.channelId` for Discord, `target.chatId` for Telegram) and persists to D1 `d1_routes`. Returns `200 { ok, count }` or `400 { error }` / `401 { error }` / `403 { error }`. Unchanged routes skip the full validation. Route filters support the `field` type (a JSONPath `path` into `payload`, arrays expand so any element matches) and 12 `op` operators (`eq` default / `ne` / `contains` / `startsWith` / `endsWith` / `regex` / `gt` / `gte` / `lt` / `lte` / `in` / `exists`); a nested `ast` (`all` / `any` / `not`) takes precedence over `filters` when present.
|
||||
- `PUT /admin/api/groups` — Validates group ids, member roles (at least one `owner`), `providers` (`github` / `gitea`), and `installationId`.
|
||||
- `POST /admin/api/test-match` — Body `{ "node": FilterNode | "filters": Filter[], "event"?: string, "payload": object }`; evaluates in memory and returns `{ matched, explanation }`. Nothing is persisted.
|
||||
- `GET/PUT /admin/api/groups/:id/fragments` — Named filter fragments (`{ id, groupId, name, node }`) stored in D1 `d1_fragments`; the editor inlines a fragment's `node` into a route's `ast` on insert (the matcher never resolves fragment references). `PUT` replaces the group's fragments and returns `200 { ok, count }`.
|
||||
- Limits: at most 200 routes and 100 groups per instance.
|
||||
|
||||
Schemas: [Routes & Targets](../guide/routes), [Groups & Access Control](../guide/groups).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue