Surface the Discord bot's moderation data on the admin panel: a read-only
staff dashboard over the existing mod_actions log, per-user history, staff
notes, and a new moderator role. No bot changes.
Schema
- users.role ENUM gains 'moderator' (CREATE + idempotent ALTER for existing DBs)
- new server-owned mod_notes table (staff_only/admin_only visibility)
Server
- model/moderation: read mod_actions via the shared pool (documented read-only
cross of the bot/server ownership boundary), correlate accounts through
user_identities (provider='discord'), flag automated actions via
staff_user_id === bot_config.application_id; pure reshaping helpers isolated
in moderation.pure.js so they unit-test without opening a DB pool
- model/modNotes: list/add with role-gated admin_only visibility
- admin/moderation.controller + routes under /api/v1/admin/moderation/* gated by
requireRole('admin','moderator'); admin_only note writes require admin
- allow assigning 'moderator' in the user create/update validators
Client
- /admin/moderation overview (window tiles, type-filterable recent feed, user
lookup) and /user/:discordId history (tabs + notes with add-note)
- RoleGate; AdminLayout filters nav and confines moderators to their section
- moderator badge + action-type/auto badges
Deferred (see plan): 6b bot event capture (joins/leaves/filter/spam), 6c appeals
(needs public accounts), 6d /internal/mod-reverse bot reversal callback.
Verified: 116 server unit tests, client build, DB-backed model smoke, full
HTTP/RBAC e2e, and a browser click-through of the dashboard.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019rao86n5cXpwAyjdBFEshV
7207 lines
188 KiB
JSON
7207 lines
188 KiB
JSON
{
|
|
"openapi": "3.0.0",
|
|
"info": {
|
|
"title": "UOMysticmoon API",
|
|
"version": "1.0.0",
|
|
"description": "REST API for the UOMysticmoon website, wiki and admin panel — a private Ultima Online shard.\n\n### Authentication\n- **Web / admin panel** uses an httpOnly session cookie (`uomm_token`) issued by `POST /api/v1/auth/login` (plus `/login/totp` when 2FA is enabled).\n- **Native / mobile clients** use bearer access tokens from `POST /api/v1/auth/mobile/login`, refreshed via `/auth/mobile/refresh`.\n\nEndpoints under `/api/v1/admin/**` require a valid session; some are further restricted to the `admin` role (editors are limited to content)."
|
|
},
|
|
"servers": [
|
|
{
|
|
"url": "/",
|
|
"description": "Same-origin (current host)"
|
|
},
|
|
{
|
|
"url": "http://localhost:3000",
|
|
"description": "Local development"
|
|
}
|
|
],
|
|
"tags": [
|
|
{
|
|
"name": "Health",
|
|
"description": "Liveness probe"
|
|
},
|
|
{
|
|
"name": "Auth",
|
|
"description": "Web session login/logout (cookie + TOTP)"
|
|
},
|
|
{
|
|
"name": "Auth · Mobile",
|
|
"description": "Native bearer-token login, refresh and logout"
|
|
},
|
|
{
|
|
"name": "Auth · SSO",
|
|
"description": "OAuth2 / OIDC provider discovery and redirect flow"
|
|
},
|
|
{
|
|
"name": "Public",
|
|
"description": "Unauthenticated site content (settings, posts, wiki, contact)"
|
|
},
|
|
{
|
|
"name": "Admin · Account",
|
|
"description": "Self-service account security (2FA, linked identities)"
|
|
},
|
|
{
|
|
"name": "Admin · Dashboard",
|
|
"description": "Dashboard summary and site mode"
|
|
},
|
|
{
|
|
"name": "Admin · Posts",
|
|
"description": "News / five-on-friday / newsletter / screenshots + uploads"
|
|
},
|
|
{
|
|
"name": "Admin · Wiki",
|
|
"description": "Wiki pages, categories, tags and revisions"
|
|
},
|
|
{
|
|
"name": "Admin · Settings",
|
|
"description": "Site settings (admin only)"
|
|
},
|
|
{
|
|
"name": "Admin · Activity",
|
|
"description": "Admin activity log"
|
|
},
|
|
{
|
|
"name": "Admin · Bot Activity",
|
|
"description": "Bot-scoring/ban state and emergency unban (admin only)"
|
|
},
|
|
{
|
|
"name": "Admin · Discord Bot",
|
|
"description": "Discord bot token/config and live status (admin only)"
|
|
},
|
|
{
|
|
"name": "Admin · Auth Providers",
|
|
"description": "SSO provider configuration (admin only)"
|
|
},
|
|
{
|
|
"name": "Admin · Users",
|
|
"description": "User management (admin only)"
|
|
}
|
|
],
|
|
"paths": {
|
|
"/api/health": {
|
|
"get": {
|
|
"tags": [
|
|
"Health"
|
|
],
|
|
"summary": "Liveness probe",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Service is up",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"status": {
|
|
"type": "string",
|
|
"example": "ok"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/login": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Log in with username and password",
|
|
"description": "On success sets the httpOnly session cookie. If the account has 2FA enabled, returns { totpRequired, challenge } instead and no cookie is set — complete login at POST /login/totp. Rate limited and behind bot/backoff guards.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Session issued, or TOTP challenge required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/LoginResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Incorrect username or password",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Too many attempts (rate limited / backoff)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/LoginRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/login/totp": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Complete login with a TOTP code",
|
|
"description": "Second step for 2FA accounts. Exchange the challenge from /login plus the current authenticator code for a session cookie.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Session issued",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/LoginResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Invalid code or expired challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Too many attempts (rate limited / backoff)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TotpLoginRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/logout": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Log out (clear the cookie and revoke this session)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Logged out",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Message"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/me": {
|
|
"get": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"summary": "Current authenticated user",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "The signed-in user",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"user": {
|
|
"$ref": "#/components/schemas/User"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/mobile/login": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth · Mobile"
|
|
],
|
|
"summary": "Native login → access + refresh tokens",
|
|
"description": "Bearer-token login for native clients. Single-request 2FA: if the account has TOTP on and no/invalid code is supplied, returns 401 { totpRequired: true } and the client retries with a code.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Access + refresh tokens",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MobileTokenResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Invalid credentials, or a TOTP code is required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Too many attempts (rate limited / backoff)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MobileLoginRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/mobile/refresh": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth · Mobile"
|
|
],
|
|
"summary": "Rotate a refresh token for a fresh token pair",
|
|
"description": "Refresh tokens are single-use: the presented token is revoked and a new access + refresh pair is issued. Reusing a rotated token fails with 401.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "New access + refresh tokens",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MobileTokenResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Invalid or expired session",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Too many refresh attempts",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MobileRefreshRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/mobile/logout": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth · Mobile"
|
|
],
|
|
"summary": "Revoke the current (or all) refresh tokens",
|
|
"description": "Requires a valid bearer access token. Revokes the given refresh token, or every session for the user when { all: true }. Idempotent.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Logged out",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Message"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid bearer token",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/MobileLogoutRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/providers": {
|
|
"get": {
|
|
"tags": [
|
|
"Auth · SSO"
|
|
],
|
|
"summary": "List enabled SSO providers",
|
|
"description": "Public discovery used by the login page to render provider buttons. Never exposes secrets.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Enabled, valid providers",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Provider"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/sso/{provider}/start": {
|
|
"get": {
|
|
"tags": [
|
|
"Auth · SSO"
|
|
],
|
|
"summary": "Begin SSO login (redirect to the IdP)",
|
|
"description": "Sets a short-lived signed transaction cookie and 302-redirects to the provider authorize URL. On error redirects back to the login page with an sso_error query param.",
|
|
"parameters": [
|
|
{
|
|
"name": "provider",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Provider id (e.g. google, discord)."
|
|
},
|
|
{
|
|
"name": "returnTo",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Internal /admin path to return to after login."
|
|
}
|
|
],
|
|
"responses": {
|
|
"302": {
|
|
"description": "Redirect to the identity provider (or back to the login page on error)"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/sso/{provider}/link": {
|
|
"get": {
|
|
"tags": [
|
|
"Auth · SSO"
|
|
],
|
|
"summary": "Begin linking an SSO identity to the current account",
|
|
"description": "Requires an authenticated session; the signed transaction captures the acting user so the callback can attach the external identity.",
|
|
"parameters": [
|
|
{
|
|
"name": "provider",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Provider id (e.g. google, discord)."
|
|
}
|
|
],
|
|
"responses": {
|
|
"302": {
|
|
"description": "Redirect to the identity provider (or back to the account page on error)"
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/auth/sso/{provider}/callback": {
|
|
"get": {
|
|
"tags": [
|
|
"Auth · SSO"
|
|
],
|
|
"summary": "OAuth redirect target — completes login or linking",
|
|
"description": "The provider redirects here with code + state. On success sets the session cookie (login) or links the identity (link), then 302-redirects into /admin. Login is link-only: unknown identities are refused (sso_error=not_linked).",
|
|
"parameters": [
|
|
{
|
|
"name": "provider",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Provider id (e.g. google, discord)."
|
|
},
|
|
{
|
|
"name": "error",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "code",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "OAuth authorization code."
|
|
},
|
|
{
|
|
"name": "state",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "OAuth state (matched against the tx cookie)."
|
|
}
|
|
],
|
|
"responses": {
|
|
"302": {
|
|
"description": "Redirect into /admin on success, or back to login/account with an error code"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/auth/sso/totp": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth · SSO"
|
|
],
|
|
"summary": "Complete an SSO login with a TOTP code",
|
|
"description": "Second step when a linked account has 2FA enabled. Reads the staged pending-TOTP cookie set by the callback plus the current authenticator code, and on success sets the session cookie. Rate limited and behind bot/backoff guards.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Session issued",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"user": {
|
|
"$ref": "#/components/schemas/SafeUser"
|
|
},
|
|
"returnTo": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"description": "Invalid code or expired challenge",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Too many attempts (rate limited / backoff)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"required": [
|
|
"code"
|
|
],
|
|
"properties": {
|
|
"code": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/public/settings": {
|
|
"get": {
|
|
"tags": [
|
|
"Public"
|
|
],
|
|
"summary": "Public site settings",
|
|
"description": "Whitelisted, non-sensitive settings the client needs to render the site.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Key/value settings",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/public/status": {
|
|
"get": {
|
|
"tags": [
|
|
"Public"
|
|
],
|
|
"summary": "Site mode / status",
|
|
"description": "Current site mode (live or maintenance) so the client can show the maintenance page.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Site status",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PublicStatus"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/public/contact": {
|
|
"post": {
|
|
"tags": [
|
|
"Public"
|
|
],
|
|
"summary": "Send a contact message",
|
|
"description": "Emails the site owner (or falls back to a mailto). Rate limited.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Message sent",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Message"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Too many messages (rate limited)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"502": {
|
|
"description": "Mail delivery failed",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ContactRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/public/posts/{category}": {
|
|
"get": {
|
|
"tags": [
|
|
"Public"
|
|
],
|
|
"summary": "List published posts in a category",
|
|
"description": "Gated by site mode: during maintenance only admins with a valid session see content.",
|
|
"parameters": [
|
|
{
|
|
"name": "category",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "news | five-on-friday | newsletter | screenshots"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Published posts",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Post"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Unknown category",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
},
|
|
"503": {
|
|
"description": "Service Unavailable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/public/posts/{category}/{idOrSlug}": {
|
|
"get": {
|
|
"tags": [
|
|
"Public"
|
|
],
|
|
"summary": "Get a single published post",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "category",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Post category."
|
|
},
|
|
{
|
|
"name": "idOrSlug",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Numeric id or slug."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "The post",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Post"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Unknown category or post not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
},
|
|
"503": {
|
|
"description": "Service Unavailable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/public/wiki": {
|
|
"get": {
|
|
"tags": [
|
|
"Public"
|
|
],
|
|
"summary": "List published wiki pages",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "q",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "category",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "tag",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Published wiki pages",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/WikiPage"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
},
|
|
"503": {
|
|
"description": "Service Unavailable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/public/wiki/categories": {
|
|
"get": {
|
|
"tags": [
|
|
"Public"
|
|
],
|
|
"summary": "List wiki categories",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Wiki categories",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/WikiCategory"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
},
|
|
"503": {
|
|
"description": "Service Unavailable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/public/wiki/tags": {
|
|
"get": {
|
|
"tags": [
|
|
"Public"
|
|
],
|
|
"summary": "List wiki tags",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Wiki tags",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
},
|
|
"503": {
|
|
"description": "Service Unavailable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/public/wiki/{slug}": {
|
|
"get": {
|
|
"tags": [
|
|
"Public"
|
|
],
|
|
"summary": "Get a single published wiki page",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "slug",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Wiki page slug."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "The wiki page",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiPage"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
},
|
|
"503": {
|
|
"description": "Service Unavailable"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/account": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Account"
|
|
],
|
|
"summary": "Get the current account (self)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "The account",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/AccountStatus"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/account/totp/setup": {
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Account"
|
|
],
|
|
"summary": "Begin 2FA enrollment (returns secret + QR)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "otpauth URL and QR data to scan",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TotpSetup"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Two-factor already enabled",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/account/totp/enable": {
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Account"
|
|
],
|
|
"summary": "Enable 2FA by confirming a code",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "2FA enabled",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TotpState"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Setup not started, or invalid code",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Two-factor already enabled",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TotpCodeRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/account/totp/disable": {
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Account"
|
|
],
|
|
"summary": "Disable 2FA by confirming a code",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "2FA disabled",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TotpState"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Not enabled, or invalid code",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TotpCodeRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/account/identities": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Account"
|
|
],
|
|
"summary": "List linked SSO identities (self)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Linked identities",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/LinkedIdentity"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/account/identities/{provider}": {
|
|
"delete": {
|
|
"tags": [
|
|
"Admin · Account"
|
|
],
|
|
"summary": "Unlink an SSO identity (self)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "provider",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Provider id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Unlinked",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnlinkedFlag"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "No linked account for that provider",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/dashboard": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Dashboard"
|
|
],
|
|
"summary": "Dashboard summary counts",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Summary: site mode, last change, post/user counts and recent activity",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"site_mode": {
|
|
"type": "string",
|
|
"example": "live"
|
|
},
|
|
"last_change": {
|
|
"type": "object",
|
|
"properties": {
|
|
"at": {
|
|
"type": "string",
|
|
"nullable": true
|
|
},
|
|
"by": {
|
|
"type": "string",
|
|
"nullable": true
|
|
}
|
|
}
|
|
},
|
|
"counts": {
|
|
"type": "object",
|
|
"properties": {
|
|
"posts": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
},
|
|
"users": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"recent_activity": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/site-mode": {
|
|
"put": {
|
|
"tags": [
|
|
"Admin · Dashboard"
|
|
],
|
|
"summary": "Set site mode (admin only)",
|
|
"description": "Switch the site between live and maintenance.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated site mode",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SiteModeState"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SiteModeRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/posts": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Posts"
|
|
],
|
|
"summary": "List all posts (including unpublished)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "category",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Optional category filter."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Posts",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Post"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Posts"
|
|
],
|
|
"summary": "Create a post",
|
|
"description": "",
|
|
"responses": {
|
|
"201": {
|
|
"description": "Created post",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Post"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error or unknown category",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PostCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/posts/upload": {
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Posts"
|
|
],
|
|
"summary": "Upload a post image (multipart)",
|
|
"description": "",
|
|
"responses": {
|
|
"201": {
|
|
"description": "Stored image URL",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"image_url": {
|
|
"type": "string",
|
|
"example": "/uploads/1700000000-abcd.png"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "No image / disallowed type",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"multipart/form-data": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"image": {
|
|
"type": "string",
|
|
"format": "binary"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/uploads": {
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Posts"
|
|
],
|
|
"summary": "Upload an image for rich-text editors (multipart)",
|
|
"description": "",
|
|
"responses": {
|
|
"201": {
|
|
"description": "Stored file URL",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UploadResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "No file / disallowed type",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"multipart/form-data": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"image": {
|
|
"type": "string",
|
|
"format": "binary"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/posts/{id}": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Posts"
|
|
],
|
|
"summary": "Get a post by id",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "Post id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "The post",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Post"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"put": {
|
|
"tags": [
|
|
"Admin · Posts"
|
|
],
|
|
"summary": "Update a post",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "Post id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated post",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Post"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error or unknown category",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PostCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Admin · Posts"
|
|
],
|
|
"summary": "Delete a post",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "Post id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Deleted (echoes the id)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/DeletedId"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/posts/{id}/publish": {
|
|
"patch": {
|
|
"tags": [
|
|
"Admin · Posts"
|
|
],
|
|
"summary": "Publish / unpublish a post",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "Post id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated post",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Post"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PublishRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/wiki/categories": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "List wiki categories",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Wiki categories",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/WikiCategory"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Create a wiki category",
|
|
"description": "",
|
|
"responses": {
|
|
"201": {
|
|
"description": "Created category",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiCategory"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Slug already exists",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiCategoryCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/wiki/categories/{id}": {
|
|
"put": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Update a wiki category",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "Category id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated category",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiCategory"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Slug already exists",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiCategoryCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Delete a wiki category",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "Category id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Deleted (echoes the id)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/DeletedId"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/wiki/tags": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "List wiki tags",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Wiki tags",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/wiki": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "List all wiki pages (including unpublished)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "q",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "category",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "tag",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "status",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Wiki pages",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/WikiPage"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Create a wiki page",
|
|
"description": "",
|
|
"responses": {
|
|
"201": {
|
|
"description": "Created wiki page",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiPage"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error or unknown category",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Slug already exists",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiPageCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/wiki/{slug}": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Get a wiki page by slug",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "slug",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Wiki page slug."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "The wiki page",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiPage"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"put": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Update a wiki page (creates a revision)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "slug",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Wiki page slug."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated wiki page",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiPage"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error or unknown category",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"allOf": [
|
|
{
|
|
"$ref": "#/components/schemas/WikiPageCreateRequest"
|
|
},
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"change_note": {
|
|
"type": "string",
|
|
"maxLength": 280
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Delete a wiki page",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "slug",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Wiki page slug."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Deleted (echoes the slug)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/DeletedSlug"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/wiki/{slug}/publish": {
|
|
"patch": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Publish / unpublish a wiki page",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "slug",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Wiki page slug."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated wiki page",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiPage"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/PublishRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/wiki/{slug}/revisions": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "List revisions of a wiki page",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "slug",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Wiki page slug."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Revisions",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/wiki/{slug}/revisions/{id}": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Get a single wiki revision",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "slug",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Wiki page slug."
|
|
},
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "Revision id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "The revision",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/wiki/{slug}/revisions/{id}/restore": {
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Wiki"
|
|
],
|
|
"summary": "Restore a wiki page to a revision",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "slug",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Wiki page slug."
|
|
},
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "Revision id to restore."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Restored wiki page",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/WikiPage"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/settings": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Settings"
|
|
],
|
|
"summary": "Get all site settings (admin only)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "All settings",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"put": {
|
|
"tags": [
|
|
"Admin · Settings"
|
|
],
|
|
"summary": "Update site settings (admin only)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated settings",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Body must be an object of key/value settings",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": true,
|
|
"description": "An object of key/value settings."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/activity": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Activity"
|
|
],
|
|
"summary": "List recent admin activity",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "offset",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "limit",
|
|
"in": "query",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "Max rows to return."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Activity entries",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/bot-activity": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Bot Activity"
|
|
],
|
|
"summary": "Bot-scoring / ban state and recent events (admin only)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Banned IPs, scores and recent events",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/bot-activity/unban": {
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Bot Activity"
|
|
],
|
|
"summary": "Emergency unban an IP (admin only)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Unbanned (echoes the ip and whether an entry was cleared)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnbanResult"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Invalid IP",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnbanRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/discord-bot/config": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Discord Bot"
|
|
],
|
|
"summary": "Get Discord bot config + live status (admin only)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Masked config + live status",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"put": {
|
|
"tags": [
|
|
"Admin · Discord Bot"
|
|
],
|
|
"summary": "Save Discord bot config (admin only)",
|
|
"description": "token is write-only — omit/blank it to keep the existing one unchanged.",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated config + live status",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error, invalid token, or missing token while enabling",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"guildId": {
|
|
"type": "string"
|
|
},
|
|
"token": {
|
|
"type": "string"
|
|
},
|
|
"enabled": {
|
|
"type": "boolean"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/auth/providers": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Auth Providers"
|
|
],
|
|
"summary": "List configured SSO providers (admin only)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Providers (secrets stripped)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/ProviderConfig"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Auth Providers"
|
|
],
|
|
"summary": "Create a custom SSO provider (admin only)",
|
|
"description": "Built-in providers (google, discord) are configured via PUT, not created here.",
|
|
"responses": {
|
|
"201": {
|
|
"description": "Created provider",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ProviderConfig"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error, or a built-in/invalid kind",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Provider id already exists",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ProviderCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/auth/providers/{id}": {
|
|
"put": {
|
|
"tags": [
|
|
"Admin · Auth Providers"
|
|
],
|
|
"summary": "Update an SSO provider (admin only)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Provider id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated provider",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ProviderConfig"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Provider not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ProviderCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Admin · Auth Providers"
|
|
],
|
|
"summary": "Delete a custom SSO provider (admin only)",
|
|
"description": "Built-in providers cannot be deleted — disable them instead.",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
},
|
|
"description": "Provider id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Deleted",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/DeletedFlag"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Built-in provider cannot be deleted",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Provider not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/moderation/stats/summary": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Moderation"
|
|
],
|
|
"summary": "Moderation action counts for 24h/7d/30d (admin or moderator)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/moderation/recent": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Moderation"
|
|
],
|
|
"summary": "Recent moderation actions, optionally filtered by type",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/moderation/search": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Moderation"
|
|
],
|
|
"summary": "Look up moderated users by Discord id or username snapshot",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "q",
|
|
"in": "query",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/moderation/user/{discordId}": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Moderation"
|
|
],
|
|
"summary": "Per-user moderation summary (counts, latest tag, linked account)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "discordId",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/moderation/user/{discordId}/actions": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Moderation"
|
|
],
|
|
"summary": "Full moderation action history for a user",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "discordId",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/admin/moderation/user/{discordId}/notes": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Moderation"
|
|
],
|
|
"summary": "Staff notes for a user (admin_only notes hidden from moderators)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "discordId",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Moderation"
|
|
],
|
|
"summary": "Add a staff note (admin_only visibility requires the admin role)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "discordId",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"201": {
|
|
"description": "Created"
|
|
},
|
|
"400": {
|
|
"description": "Bad Request"
|
|
},
|
|
"403": {
|
|
"description": "Forbidden"
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object",
|
|
"properties": {
|
|
"visibility": {
|
|
"example": "any"
|
|
},
|
|
"body": {
|
|
"example": "any"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/users": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin · Users"
|
|
],
|
|
"summary": "List users (admin only)",
|
|
"description": "",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Users",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/User"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Admin · Users"
|
|
],
|
|
"summary": "Create a user (admin only)",
|
|
"description": "",
|
|
"responses": {
|
|
"201": {
|
|
"description": "Created user",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/User"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Username already taken",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/admin/users/{id}": {
|
|
"put": {
|
|
"tags": [
|
|
"Admin · Users"
|
|
],
|
|
"summary": "Update a user (admin only)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "User id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Updated user",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/User"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Validation error, or cannot demote the last admin",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"409": {
|
|
"description": "Username already taken",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UserCreateRequest"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Admin · Users"
|
|
],
|
|
"summary": "Delete a user (admin only)",
|
|
"description": "",
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
},
|
|
"description": "User id."
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Deleted (echoes the id)",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/DeletedId"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Cannot delete your own account or the last admin",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Not authenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Admin role required",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"cookieAuth": []
|
|
},
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"securitySchemes": {
|
|
"cookieAuth": {
|
|
"type": "apiKey",
|
|
"in": "cookie",
|
|
"name": "uomm_token",
|
|
"description": "Session JWT set as an httpOnly cookie by POST /api/v1/auth/login."
|
|
},
|
|
"bearerAuth": {
|
|
"type": "http",
|
|
"scheme": "bearer",
|
|
"bearerFormat": "JWT",
|
|
"description": "Access token from POST /api/v1/auth/mobile/login (or /refresh)."
|
|
}
|
|
},
|
|
"schemas": {
|
|
"Error": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"message": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Not found"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"ValidationError": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"errors": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "array"
|
|
},
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "field"
|
|
}
|
|
}
|
|
},
|
|
"msg": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Invalid value"
|
|
}
|
|
}
|
|
},
|
|
"path": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "username"
|
|
}
|
|
}
|
|
},
|
|
"location": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "body"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"SafeUser": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 1
|
|
}
|
|
}
|
|
},
|
|
"username": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "admin"
|
|
}
|
|
}
|
|
},
|
|
"role": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"enum": {
|
|
"type": "array",
|
|
"example": [
|
|
"admin",
|
|
"editor"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "admin"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"LoginRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"username",
|
|
"password"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"username": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "admin"
|
|
}
|
|
}
|
|
},
|
|
"password": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "password"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "super-secret"
|
|
}
|
|
}
|
|
},
|
|
"company": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Honeypot — must be empty for humans."
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": ""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"LoginResponse": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Either a session (user) or, for 2FA accounts, a TOTP challenge to complete at /login/totp."
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"user": {
|
|
"$ref": "#/components/schemas/SafeUser"
|
|
},
|
|
"totpRequired": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"challenge": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Signed challenge token for the TOTP step."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"TotpLoginRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"challenge",
|
|
"code"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"challenge": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Token returned by /login when totpRequired."
|
|
}
|
|
}
|
|
},
|
|
"code": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "123456"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"MobileLoginRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"username",
|
|
"password"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"username": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "admin"
|
|
}
|
|
}
|
|
},
|
|
"password": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "password"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "super-secret"
|
|
}
|
|
}
|
|
},
|
|
"code": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "TOTP code (only when 2FA is enabled)."
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "123456"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"MobileTokenResponse": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"accessToken": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Short-lived bearer JWT."
|
|
}
|
|
}
|
|
},
|
|
"refreshToken": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Long-lived, revocable refresh token."
|
|
}
|
|
}
|
|
},
|
|
"expiresIn": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Access token lifetime as a duration string (zeit/ms format, e.g. \"15m\")."
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "15m"
|
|
}
|
|
}
|
|
},
|
|
"user": {
|
|
"$ref": "#/components/schemas/SafeUser"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"MobileRefreshRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"refreshToken"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"refreshToken": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"MobileLogoutRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"refreshToken": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Revoke a single session."
|
|
}
|
|
}
|
|
},
|
|
"all": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Revoke every session for the user."
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"Message": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"message": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Logged out."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"ContactRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"message"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"message": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 5000
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "When does the shard launch?"
|
|
}
|
|
}
|
|
},
|
|
"email": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "email"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "player@example.com"
|
|
}
|
|
}
|
|
},
|
|
"name": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 100
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Lord British"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"Provider": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "google"
|
|
}
|
|
}
|
|
},
|
|
"name": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Google"
|
|
}
|
|
}
|
|
},
|
|
"icon": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Icon hint — the provider kind ('google' | 'discord' | 'oidc' | 'oauth2')."
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "google"
|
|
}
|
|
}
|
|
},
|
|
"loginUrl": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Relative URL to begin the redirect flow."
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "/api/v1/auth/sso/google/start"
|
|
}
|
|
}
|
|
},
|
|
"priority": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Sort order (ascending)."
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"ProviderConfig": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "okta"
|
|
}
|
|
}
|
|
},
|
|
"kind": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"enum": {
|
|
"type": "array",
|
|
"example": [
|
|
"google",
|
|
"discord",
|
|
"oidc",
|
|
"oauth2"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "oidc"
|
|
}
|
|
}
|
|
},
|
|
"name": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Okta"
|
|
}
|
|
}
|
|
},
|
|
"enabled": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"clientId": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
},
|
|
"hasSecret": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Whether a client secret is stored (the secret itself is never returned)."
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"authorizeUrl": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "uri"
|
|
}
|
|
}
|
|
},
|
|
"tokenUrl": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "uri"
|
|
}
|
|
}
|
|
},
|
|
"userinfoUrl": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "uri"
|
|
}
|
|
}
|
|
},
|
|
"scopes": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "openid email profile"
|
|
}
|
|
}
|
|
},
|
|
"priority": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 10
|
|
}
|
|
}
|
|
},
|
|
"builtin": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "True for the fixed google/discord providers."
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": false
|
|
}
|
|
}
|
|
},
|
|
"health": {
|
|
"$ref": "#/components/schemas/ProviderHealth"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"ProviderHealth": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Config-completeness check that gates whether a provider is offered to end users."
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"valid": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"missing": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "array"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Names of required config fields that are still missing."
|
|
},
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "array",
|
|
"example": [],
|
|
"items": {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"ProviderCreateRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"id",
|
|
"kind",
|
|
"name"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"pattern": {
|
|
"type": "string",
|
|
"example": "^[a-z0-9-]+$"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "okta"
|
|
}
|
|
}
|
|
},
|
|
"kind": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"enum": {
|
|
"type": "array",
|
|
"example": [
|
|
"oidc",
|
|
"oauth2"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "oidc"
|
|
}
|
|
}
|
|
},
|
|
"name": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 80
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Okta"
|
|
}
|
|
}
|
|
},
|
|
"enabled": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"clientId": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
},
|
|
"secret": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "password"
|
|
}
|
|
}
|
|
},
|
|
"authorizeUrl": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "uri"
|
|
}
|
|
}
|
|
},
|
|
"tokenUrl": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "uri"
|
|
}
|
|
}
|
|
},
|
|
"userinfoUrl": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "uri"
|
|
}
|
|
}
|
|
},
|
|
"scopes": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 500
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "openid email profile"
|
|
}
|
|
}
|
|
},
|
|
"priority": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 10
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"Post": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 12
|
|
}
|
|
}
|
|
},
|
|
"category": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "news"
|
|
}
|
|
}
|
|
},
|
|
"title": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Server maintenance this weekend"
|
|
}
|
|
}
|
|
},
|
|
"slug": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "server-maintenance-this-weekend"
|
|
}
|
|
}
|
|
},
|
|
"excerpt": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"nullable": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"body": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"nullable": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"image_url": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"nullable": {
|
|
"type": "boolean",
|
|
"example": true
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "/uploads/1700000000-abcd.png"
|
|
}
|
|
}
|
|
},
|
|
"published": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"author_id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"nullable": {
|
|
"type": "boolean",
|
|
"example": true
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 1
|
|
}
|
|
}
|
|
},
|
|
"created_at": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"updated_at": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"published_at": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "date-time"
|
|
},
|
|
"nullable": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"PostCreateRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"category",
|
|
"title"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"category": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "news"
|
|
}
|
|
}
|
|
},
|
|
"title": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 200
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Server maintenance this weekend"
|
|
}
|
|
}
|
|
},
|
|
"body": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
},
|
|
"image_url": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Required for the screenshots category."
|
|
}
|
|
}
|
|
},
|
|
"published": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"PublishRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"published"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"published": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"UploadResponse": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"url": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "/uploads/1700000000-abcd.png"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"WikiPage": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 3
|
|
}
|
|
}
|
|
},
|
|
"slug": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "getting-started"
|
|
}
|
|
}
|
|
},
|
|
"title": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Getting Started"
|
|
}
|
|
}
|
|
},
|
|
"excerpt": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
},
|
|
"body": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
},
|
|
"category_id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"nullable": {
|
|
"type": "boolean",
|
|
"example": true
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 2
|
|
}
|
|
}
|
|
},
|
|
"published": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"tags": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "array"
|
|
},
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "array",
|
|
"example": [
|
|
"newbie",
|
|
"guide"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"created_at": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"updated_at": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "date-time"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"WikiPageCreateRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"slug",
|
|
"title"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"slug": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"pattern": {
|
|
"type": "string",
|
|
"example": "^[a-z0-9-]+$"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "getting-started"
|
|
}
|
|
}
|
|
},
|
|
"title": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 200
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Getting Started"
|
|
}
|
|
}
|
|
},
|
|
"excerpt": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 400
|
|
}
|
|
}
|
|
},
|
|
"body": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
},
|
|
"category_id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"nullable": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"published": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": false
|
|
}
|
|
}
|
|
},
|
|
"tags": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "array"
|
|
},
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"WikiCategory": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 2
|
|
}
|
|
}
|
|
},
|
|
"slug": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "guides"
|
|
}
|
|
}
|
|
},
|
|
"title": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Guides"
|
|
}
|
|
}
|
|
},
|
|
"description": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
}
|
|
}
|
|
},
|
|
"sort_order": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"WikiCategoryCreateRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"slug",
|
|
"title"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"slug": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"pattern": {
|
|
"type": "string",
|
|
"example": "^[a-z0-9-]+$"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "guides"
|
|
}
|
|
}
|
|
},
|
|
"title": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 200
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "Guides"
|
|
}
|
|
}
|
|
},
|
|
"description": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 400
|
|
}
|
|
}
|
|
},
|
|
"sort_order": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"User": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 1
|
|
}
|
|
}
|
|
},
|
|
"username": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "admin"
|
|
}
|
|
}
|
|
},
|
|
"role": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"enum": {
|
|
"type": "array",
|
|
"example": [
|
|
"admin",
|
|
"editor"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "admin"
|
|
}
|
|
}
|
|
},
|
|
"totp_enabled": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"last_login_at": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "date-time"
|
|
},
|
|
"nullable": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
},
|
|
"created_at": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "date-time"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"UserCreateRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"username",
|
|
"password"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"username": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"minLength": {
|
|
"type": "number",
|
|
"example": 3
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 32
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "editor1"
|
|
}
|
|
}
|
|
},
|
|
"password": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "password"
|
|
},
|
|
"minLength": {
|
|
"type": "number",
|
|
"example": 8
|
|
},
|
|
"maxLength": {
|
|
"type": "number",
|
|
"example": 64
|
|
}
|
|
}
|
|
},
|
|
"role": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"enum": {
|
|
"type": "array",
|
|
"example": [
|
|
"admin",
|
|
"editor"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "editor"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"TotpCodeRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"code"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"code": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "123456"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"SiteModeRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"mode"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"mode": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"enum": {
|
|
"type": "array",
|
|
"example": [
|
|
"live",
|
|
"maintenance"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "live"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"UnbanRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"required": {
|
|
"type": "array",
|
|
"example": [
|
|
"ip"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ip": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "203.0.113.5"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"AccountStatus": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Self-service account security status (GET /admin/account)."
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 1
|
|
}
|
|
}
|
|
},
|
|
"username": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "admin"
|
|
}
|
|
}
|
|
},
|
|
"role": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"enum": {
|
|
"type": "array",
|
|
"example": [
|
|
"admin",
|
|
"editor"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "admin"
|
|
}
|
|
}
|
|
},
|
|
"totp_enabled": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"TotpSetup": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Enrollment material returned by POST /account/totp/setup."
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"otpauthUrl": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "otpauth://totp/UOMysticmoon:admin?secret=..."
|
|
}
|
|
}
|
|
},
|
|
"qr": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "QR code as a data: URL."
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "data:image/png;base64,iVBORw0KGgo..."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"TotpState": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Result of enabling/disabling 2FA."
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"totp_enabled": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"LinkedIdentity": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"provider": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "google"
|
|
}
|
|
}
|
|
},
|
|
"email": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "email"
|
|
},
|
|
"nullable": {
|
|
"type": "boolean",
|
|
"example": true
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "user@example.com"
|
|
}
|
|
}
|
|
},
|
|
"linked_at": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "date-time"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"SiteModeState": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Result of PUT /admin/site-mode."
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"site_mode": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"enum": {
|
|
"type": "array",
|
|
"example": [
|
|
"live",
|
|
"maintenance"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "maintenance"
|
|
}
|
|
}
|
|
},
|
|
"changed_at": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"example": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"changed_by": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "admin"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"PublicStatus": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Public site status (GET /public/status)."
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"mode": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"enum": {
|
|
"type": "array",
|
|
"example": [
|
|
"live",
|
|
"maintenance"
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "live"
|
|
}
|
|
}
|
|
},
|
|
"status_message": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": ""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"DeletedId": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "integer"
|
|
},
|
|
"example": {
|
|
"type": "number",
|
|
"example": 12
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"DeletedSlug": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"slug": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "getting-started"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"DeletedFlag": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"deleted": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"UnlinkedFlag": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"unlinked": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"UnbanResult": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "object"
|
|
},
|
|
"properties": {
|
|
"type": "object",
|
|
"properties": {
|
|
"ip": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "string"
|
|
},
|
|
"example": {
|
|
"type": "string",
|
|
"example": "203.0.113.5"
|
|
}
|
|
}
|
|
},
|
|
"removed": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"example": "boolean"
|
|
},
|
|
"description": {
|
|
"type": "string",
|
|
"example": "Whether the IP had an entry that was cleared."
|
|
},
|
|
"example": {
|
|
"type": "boolean",
|
|
"example": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |