mirror of
https://github.com/ReCloudStudio/WebHooker.git
synced 2026-09-22 16:11:29 +00:00
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.
8.2 KiB
8.2 KiB
Admin API
Admin endpoints manage routes, groups, members, invites, webhook secrets, send logs, and the audit log. They require an admin session cookie obtained via GET /admin/login (GitHub OAuth); the signed-in user must be listed in ADMIN_USER_IDS or manage a group. See Configuration → Web UI for setup.
The console itself is served at /admin; its tabs are deep-linkable via the URL path (/admin/groups, /admin/logs, /admin/audit).
Endpoints
| Endpoint | Description |
|---|---|
GET /admin |
Config console UI |
GET /admin/login |
Start admin sign-in (GitHub OAuth) |
GET /admin/logout |
Sign out and destroy the session |
GET /admin/invite?token=… |
Accept a group invite (browser page) |
GET /admin/api/me |
Current session, scope, groups, and roles |
GET /admin/api/routes |
List routes (scoped to access) |
PUT /admin/api/routes |
Replace routes (owner/admin per group) |
GET /admin/api/groups |
List groups + the signed-in user's role in each |
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) |
DELETE /admin/api/invites/:token |
Revoke an invite (owner) |
GET /admin/api/groups/:id/webhook |
Group webhook endpoint info (owner) |
POST /admin/api/groups/:id/webhook/regenerate |
Generate/regenerate the group webhook secret (owner) |
DELETE /admin/api/groups/:id/webhook |
Disable the group webhook ingress (owner) |
GET /admin/api/logs |
Send logs (scoped to accessible routes) |
GET /admin/api/logs/:id |
Single send-log entry (scoped) |
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 forfallbackroutes — optionaldiscordRoleIds(list of role id strings), and platform-aware targets:target.channelIdfor Discord,target.chatIdfor Telegram) and persists to D1d1_routes. Returns200 { ok, count }or400 { error }/401 { error }/403 { error }. Unchanged routes skip the full validation. Route filters support thefieldtype (a JSONPathpathintopayload, arrays expand so any element matches) and 12opoperators (eqdefault /ne/contains/startsWith/endsWith/regex/gt/gte/lt/lte/in/exists); a nestedast(all/any/not) takes precedence overfilterswhen present.PUT /admin/api/groups— Validates group ids, member roles (at least oneowner),providers(github/gitea), andinstallationId.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 D1d1_fragments; the editor inlines a fragment'snodeinto a route'saston insert (the matcher never resolves fragment references).PUTreplaces the group's fragments and returns200 { ok, count }.- Limits: at most 200 routes and 100 groups per instance.
Schemas: Routes & Targets, Groups & Access Control.