protected
This commit is contained in:
@@ -1,6 +1,18 @@
|
|||||||
import { createSignal, For, Show } from "solid-js";
|
import { createSignal, For, Show } from "solid-js";
|
||||||
|
import { query, createAsync } from "@solidjs/router";
|
||||||
|
import { getRequestEvent } from "solid-js/web";
|
||||||
|
import { getPrivilegeLevel } from "~/server/utils";
|
||||||
import { api } from "~/lib/api";
|
import { api } from "~/lib/api";
|
||||||
|
|
||||||
|
const getAuthState = query(async () => {
|
||||||
|
"use server";
|
||||||
|
|
||||||
|
const event = getRequestEvent()!;
|
||||||
|
const privilegeLevel = await getPrivilegeLevel(event.nativeEvent);
|
||||||
|
|
||||||
|
return { privilegeLevel };
|
||||||
|
}, "test-auth-state");
|
||||||
|
|
||||||
type EndpointTest = {
|
type EndpointTest = {
|
||||||
name: string;
|
name: string;
|
||||||
router: string;
|
router: string;
|
||||||
@@ -846,6 +858,8 @@ const routerSections: RouterSection[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export default function TestPage() {
|
export default function TestPage() {
|
||||||
|
const authState = createAsync(() => getAuthState());
|
||||||
|
|
||||||
const [expandedSections, setExpandedSections] = createSignal<Set<string>>(
|
const [expandedSections, setExpandedSections] = createSignal<Set<string>>(
|
||||||
new Set()
|
new Set()
|
||||||
);
|
);
|
||||||
@@ -919,282 +933,297 @@ export default function TestPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main class="min-h-screen p-8">
|
<Show
|
||||||
<div class="mx-auto max-w-6xl">
|
when={authState()?.privilegeLevel === "admin"}
|
||||||
<div class="bg-surface0 mb-6 rounded-lg p-6 shadow-lg">
|
fallback={
|
||||||
<h1 class="mb-2 text-3xl font-bold">tRPC API Testing Dashboard</h1>
|
<div class="w-full pt-[30vh] text-center">
|
||||||
<p class="text-text mb-4">
|
<div class="text-text text-2xl">Unauthorized</div>
|
||||||
Complete API coverage: Example, Auth, Database, User, Misc, and
|
<div class="text-subtext0 mt-4">
|
||||||
Lineage routers
|
You must be an admin to access this page.
|
||||||
</p>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="border-lavender bg-mauve rounded border p-4">
|
}
|
||||||
<p class="text-base text-sm">
|
>
|
||||||
<strong>Quick Start:</strong> Expand any section below to test
|
<main class="min-h-screen p-8">
|
||||||
endpoints. Public endpoints work immediately. Auth-required
|
<div class="mx-auto max-w-6xl">
|
||||||
endpoints need valid tokens.
|
<div class="bg-surface0 mb-6 rounded-lg p-6 shadow-lg">
|
||||||
|
<h1 class="mb-2 text-3xl font-bold">tRPC API Testing Dashboard</h1>
|
||||||
|
<p class="text-text mb-4">
|
||||||
|
Complete API coverage: Example, Auth, Database, User, Misc, and
|
||||||
|
Lineage routers
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div class="border-lavender bg-mauve rounded border p-4">
|
||||||
|
<p class="text-base text-sm">
|
||||||
|
<strong>Quick Start:</strong> Expand any section below to test
|
||||||
|
endpoints. Public endpoints work immediately. Auth-required
|
||||||
|
endpoints need valid tokens.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<For each={routerSections}>
|
<For each={routerSections}>
|
||||||
{(section) => {
|
{(section) => {
|
||||||
const isExpanded = () => expandedSections().has(section.name);
|
const isExpanded = () => expandedSections().has(section.name);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="bg-surface0 rounded-lg shadow">
|
<div class="bg-surface0 rounded-lg shadow">
|
||||||
{/* Section Header */}
|
{/* Section Header */}
|
||||||
<button
|
<button
|
||||||
onClick={() => toggleSection(section.name)}
|
onClick={() => toggleSection(section.name)}
|
||||||
class="flex w-full items-center justify-between px-6 py-4 transition"
|
class="flex w-full items-center justify-between px-6 py-4 transition"
|
||||||
>
|
>
|
||||||
<div class="text-left">
|
<div class="text-left">
|
||||||
<h2 class="text-xl font-bold">{section.name}</h2>
|
<h2 class="text-xl font-bold">{section.name}</h2>
|
||||||
<p class="text-subtext0 text-sm">{section.description}</p>
|
<p class="text-subtext0 text-sm">
|
||||||
<p class="text-subtext1 mt-1 text-xs">
|
{section.description}
|
||||||
{section.endpoints.length} endpoint
|
</p>
|
||||||
{section.endpoints.length !== 1 ? "s" : ""}
|
<p class="text-subtext1 mt-1 text-xs">
|
||||||
</p>
|
{section.endpoints.length} endpoint
|
||||||
</div>
|
{section.endpoints.length !== 1 ? "s" : ""}
|
||||||
<div class="text-subtext1 text-2xl">
|
</p>
|
||||||
{isExpanded() ? "−" : "+"}
|
</div>
|
||||||
</div>
|
<div class="text-subtext1 text-2xl">
|
||||||
</button>
|
{isExpanded() ? "−" : "+"}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
{/* Section Content */}
|
{/* Section Content */}
|
||||||
<Show when={isExpanded()}>
|
<Show when={isExpanded()}>
|
||||||
<div class="border-base space-y-4 border-t p-6">
|
<div class="border-base space-y-4 border-t p-6">
|
||||||
<For each={section.endpoints}>
|
<For each={section.endpoints}>
|
||||||
{(endpoint) => {
|
{(endpoint) => {
|
||||||
const key = `${endpoint.router}.${endpoint.procedure}`;
|
const key = `${endpoint.router}.${endpoint.procedure}`;
|
||||||
const hasInput = endpoint.sampleInput !== undefined;
|
const hasInput = endpoint.sampleInput !== undefined;
|
||||||
const displayInput = () => {
|
const displayInput = () => {
|
||||||
if (inputEdits()[key]) {
|
if (inputEdits()[key]) {
|
||||||
return inputEdits()[key];
|
return inputEdits()[key];
|
||||||
}
|
}
|
||||||
// Handle primitive values (string, number, boolean)
|
// Handle primitive values (string, number, boolean)
|
||||||
if (typeof endpoint.sampleInput === "string") {
|
if (typeof endpoint.sampleInput === "string") {
|
||||||
return `"${endpoint.sampleInput}"`;
|
return `"${endpoint.sampleInput}"`;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
typeof endpoint.sampleInput === "number" ||
|
typeof endpoint.sampleInput === "number" ||
|
||||||
typeof endpoint.sampleInput === "boolean"
|
typeof endpoint.sampleInput === "boolean"
|
||||||
) {
|
) {
|
||||||
return String(endpoint.sampleInput);
|
return String(endpoint.sampleInput);
|
||||||
}
|
}
|
||||||
// Handle objects and arrays
|
// Handle objects and arrays
|
||||||
return JSON.stringify(
|
return JSON.stringify(
|
||||||
endpoint.sampleInput,
|
endpoint.sampleInput,
|
||||||
null,
|
null,
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="bg-surface2 border-surface1 rounded-lg border p-4">
|
<div class="bg-surface2 border-surface1 rounded-lg border p-4">
|
||||||
{/* Endpoint Header */}
|
{/* Endpoint Header */}
|
||||||
<div class="mb-3 flex items-start justify-between">
|
<div class="mb-3 flex items-start justify-between">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<h3 class="text-subtext0 text-lg font-semibold">
|
<h3 class="text-subtext0 text-lg font-semibold">
|
||||||
{endpoint.name}
|
{endpoint.name}
|
||||||
</h3>
|
</h3>
|
||||||
<Show when={endpoint.requiresAuth}>
|
<Show when={endpoint.requiresAuth}>
|
||||||
<span class="bg-surface1 text-yellow rounded px-2 py-1 text-xs">
|
<span class="bg-surface1 text-yellow rounded px-2 py-1 text-xs">
|
||||||
🔒 Auth Required
|
🔒 Auth Required
|
||||||
|
</span>
|
||||||
|
</Show>
|
||||||
|
<Show when={endpoint.requiresAdmin}>
|
||||||
|
<span class="bg-maroon rounded px-2 py-1 text-base text-xs">
|
||||||
|
👑 Admin Only
|
||||||
|
</span>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
<p class="mt-1 text-sm text-gray-600">
|
||||||
|
{endpoint.description}
|
||||||
|
</p>
|
||||||
|
<div class="mt-2 flex gap-2">
|
||||||
|
<code class="bg-surface0 rounded px-2 py-1 text-xs">
|
||||||
|
{key}
|
||||||
|
</code>
|
||||||
|
<span class="bg-blue text-text rounded px-2 py-1 text-xs">
|
||||||
|
{endpoint.method === "query"
|
||||||
|
? "GET"
|
||||||
|
: "POST"}
|
||||||
</span>
|
</span>
|
||||||
</Show>
|
</div>
|
||||||
<Show when={endpoint.requiresAdmin}>
|
|
||||||
<span class="bg-maroon rounded px-2 py-1 text-base text-xs">
|
|
||||||
👑 Admin Only
|
|
||||||
</span>
|
|
||||||
</Show>
|
|
||||||
</div>
|
|
||||||
<p class="mt-1 text-sm text-gray-600">
|
|
||||||
{endpoint.description}
|
|
||||||
</p>
|
|
||||||
<div class="mt-2 flex gap-2">
|
|
||||||
<code class="bg-surface0 rounded px-2 py-1 text-xs">
|
|
||||||
{key}
|
|
||||||
</code>
|
|
||||||
<span class="bg-blue text-text rounded px-2 py-1 text-xs">
|
|
||||||
{endpoint.method === "query"
|
|
||||||
? "GET"
|
|
||||||
: "POST"}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => testEndpoint(endpoint)}
|
||||||
|
disabled={loading()[key]}
|
||||||
|
class="bg-green ml-4 rounded px-4 py-2 text-base font-semibold whitespace-nowrap transition hover:brightness-125 disabled:brightness-50"
|
||||||
|
>
|
||||||
|
{loading()[key] ? "Testing..." : "Test"}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button
|
|
||||||
onClick={() => testEndpoint(endpoint)}
|
{/* Input Editor */}
|
||||||
disabled={loading()[key]}
|
<Show when={hasInput}>
|
||||||
class="bg-green ml-4 rounded px-4 py-2 text-base font-semibold whitespace-nowrap transition hover:brightness-125 disabled:brightness-50"
|
<div class="mb-3">
|
||||||
>
|
<label class="text-text mb-1 block text-xs font-semibold">
|
||||||
{loading()[key] ? "Testing..." : "Test"}
|
Request Body (edit JSON):
|
||||||
</button>
|
</label>
|
||||||
|
<textarea
|
||||||
|
value={displayInput()}
|
||||||
|
onInput={(e) =>
|
||||||
|
updateInput(key, e.currentTarget.value)
|
||||||
|
}
|
||||||
|
class="border-lavender bg-crust min-h-[100px] w-full rounded border p-2 font-mono text-xs"
|
||||||
|
spellcheck={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
{/* Error Display */}
|
||||||
|
<Show when={errors()[key]}>
|
||||||
|
<div class="mb-3 rounded border border-red-200 bg-red-50 p-3">
|
||||||
|
<p class="text-sm font-semibold text-red-800">
|
||||||
|
Error:
|
||||||
|
</p>
|
||||||
|
<p class="font-mono text-sm text-red-600">
|
||||||
|
{errors()[key]}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
{/* Results Display */}
|
||||||
|
<Show when={results()[key]}>
|
||||||
|
<div class="rounded bg-gray-900 p-3">
|
||||||
|
<p class="mb-2 text-xs font-semibold text-green-400">
|
||||||
|
✓ Response:
|
||||||
|
</p>
|
||||||
|
<pre class="max-h-60 overflow-auto text-xs text-green-400">
|
||||||
|
{JSON.stringify(results()[key], null, 2)}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Input Editor */}
|
{/* Footer Instructions */}
|
||||||
<Show when={hasInput}>
|
<div class="bg-overlay2 mt-6 rounded-lg p-6 shadow-lg">
|
||||||
<div class="mb-3">
|
<h2 class="text-crust mb-4 text-2xl font-bold">Testing Guide</h2>
|
||||||
<label class="text-text mb-1 block text-xs font-semibold">
|
|
||||||
Request Body (edit JSON):
|
|
||||||
</label>
|
|
||||||
<textarea
|
|
||||||
value={displayInput()}
|
|
||||||
onInput={(e) =>
|
|
||||||
updateInput(key, e.currentTarget.value)
|
|
||||||
}
|
|
||||||
class="border-lavender bg-crust min-h-[100px] w-full rounded border p-2 font-mono text-xs"
|
|
||||||
spellcheck={false}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
{/* Error Display */}
|
<div class="space-y-4 text-base">
|
||||||
<Show when={errors()[key]}>
|
<div>
|
||||||
<div class="mb-3 rounded border border-red-200 bg-red-50 p-3">
|
<h3 class="mb-2 text-lg font-semibold">🟢 No Auth Required</h3>
|
||||||
<p class="text-sm font-semibold text-red-800">
|
<ul class="ml-6 list-disc space-y-1 text-sm">
|
||||||
Error:
|
<li>
|
||||||
</p>
|
<strong>Example Router</strong> - Hello endpoint
|
||||||
<p class="font-mono text-sm text-red-600">
|
</li>
|
||||||
{errors()[key]}
|
<li>
|
||||||
</p>
|
<strong>Lineage JSON Service</strong> - All 6 endpoints work
|
||||||
</div>
|
immediately
|
||||||
</Show>
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Database</strong> - All endpoints (comments, posts,
|
||||||
|
users, reactions, likes)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Misc</strong> - Downloads, S3 operations, password
|
||||||
|
utilities
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Lineage Misc</strong> - Offline Secret, Get
|
||||||
|
Opponents
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Lineage PvP</strong> - Get Opponents
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Results Display */}
|
<div>
|
||||||
<Show when={results()[key]}>
|
<h3 class="mb-2 text-lg font-semibold">🟡 Auth Required</h3>
|
||||||
<div class="rounded bg-gray-900 p-3">
|
<p class="mb-2 text-sm">
|
||||||
<p class="mb-2 text-xs font-semibold text-green-400">
|
These need valid JWT tokens from login/registration:
|
||||||
✓ Response:
|
</p>
|
||||||
</p>
|
<ul class="ml-6 list-disc space-y-1 text-sm">
|
||||||
<pre class="max-h-60 overflow-auto text-xs text-green-400">
|
<li>
|
||||||
{JSON.stringify(results()[key], null, 2)}
|
<strong>Example Router</strong> - Get Profile
|
||||||
</pre>
|
</li>
|
||||||
</div>
|
<li>
|
||||||
</Show>
|
<strong>User Router</strong> - All endpoints (profile
|
||||||
</div>
|
updates, password, account deletion)
|
||||||
);
|
</li>
|
||||||
}}
|
<li>
|
||||||
</For>
|
<strong>Lineage Auth</strong> - Email Login, Refresh Token
|
||||||
</div>
|
</li>
|
||||||
</Show>
|
<li>
|
||||||
</div>
|
<strong>Lineage Database</strong> - Get Credentials,
|
||||||
);
|
Deletion endpoints
|
||||||
}}
|
</li>
|
||||||
</For>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Footer Instructions */}
|
<div>
|
||||||
<div class="bg-overlay2 mt-6 rounded-lg p-6 shadow-lg">
|
<h3 class="mb-2 text-lg font-semibold">🔴 Admin Required</h3>
|
||||||
<h2 class="text-crust mb-4 text-2xl font-bold">Testing Guide</h2>
|
<p class="mb-2 text-sm">
|
||||||
|
Maintenance endpoints require admin privileges (userIDToken
|
||||||
|
cookie with ADMIN_ID).
|
||||||
|
</p>
|
||||||
|
<ul class="ml-6 list-disc space-y-1 text-sm">
|
||||||
|
<li>
|
||||||
|
<strong>Example Router</strong> - Admin Dashboard
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Lineage Maintenance</strong> - Find Loose Databases,
|
||||||
|
Cleanup Expired
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="space-y-4 text-base">
|
<div>
|
||||||
<div>
|
<h3 class="mb-2 text-lg font-semibold">📝 Typical Workflows</h3>
|
||||||
<h3 class="mb-2 text-lg font-semibold">🟢 No Auth Required</h3>
|
<ol class="ml-6 list-decimal space-y-2 text-sm">
|
||||||
<ul class="ml-6 list-disc space-y-1 text-sm">
|
<li>
|
||||||
<li>
|
<strong>Test public endpoints:</strong> Start with Example
|
||||||
<strong>Example Router</strong> - Hello endpoint
|
Hello, Lineage JSON Service, or Database queries
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Lineage JSON Service</strong> - All 6 endpoints work
|
<strong>OAuth flow:</strong> Use Auth router callbacks with
|
||||||
immediately
|
OAuth codes from GitHub/Google
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Database</strong> - All endpoints (comments, posts,
|
<strong>Email auth flow:</strong> Register → verify email →
|
||||||
users, reactions, likes)
|
login → use JWT
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Misc</strong> - Downloads, S3 operations, password
|
<strong>Blog/Project management:</strong> Create posts → add
|
||||||
utilities
|
comments/likes → upload images via S3
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<strong>Lineage Misc</strong> - Offline Secret, Get Opponents
|
<strong>Lineage game data:</strong> Fetch JSON data →
|
||||||
</li>
|
register character → find PvP opponents
|
||||||
<li>
|
</li>
|
||||||
<strong>Lineage PvP</strong> - Get Opponents
|
</ol>
|
||||||
</li>
|
</div>
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div class="border-rosewater bg-rosewater mt-4 rounded border p-4">
|
||||||
<h3 class="mb-2 text-lg font-semibold">🟡 Auth Required</h3>
|
<p class="text-crust text-sm">
|
||||||
<p class="mb-2 text-sm">
|
<strong>Note:</strong> Some endpoints require specific setup
|
||||||
These need valid JWT tokens from login/registration:
|
(e.g., OAuth codes, existing database records, valid S3 keys).
|
||||||
</p>
|
Check the sample input to understand what data each endpoint
|
||||||
<ul class="ml-6 list-disc space-y-1 text-sm">
|
expects.
|
||||||
<li>
|
</p>
|
||||||
<strong>Example Router</strong> - Get Profile
|
</div>
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>User Router</strong> - All endpoints (profile updates,
|
|
||||||
password, account deletion)
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Lineage Auth</strong> - Email Login, Refresh Token
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Lineage Database</strong> - Get Credentials, Deletion
|
|
||||||
endpoints
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 class="mb-2 text-lg font-semibold">🔴 Admin Required</h3>
|
|
||||||
<p class="mb-2 text-sm">
|
|
||||||
Maintenance endpoints require admin privileges (userIDToken
|
|
||||||
cookie with ADMIN_ID).
|
|
||||||
</p>
|
|
||||||
<ul class="ml-6 list-disc space-y-1 text-sm">
|
|
||||||
<li>
|
|
||||||
<strong>Example Router</strong> - Admin Dashboard
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Lineage Maintenance</strong> - Find Loose Databases,
|
|
||||||
Cleanup Expired
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 class="mb-2 text-lg font-semibold">📝 Typical Workflows</h3>
|
|
||||||
<ol class="ml-6 list-decimal space-y-2 text-sm">
|
|
||||||
<li>
|
|
||||||
<strong>Test public endpoints:</strong> Start with Example
|
|
||||||
Hello, Lineage JSON Service, or Database queries
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>OAuth flow:</strong> Use Auth router callbacks with
|
|
||||||
OAuth codes from GitHub/Google
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Email auth flow:</strong> Register → verify email →
|
|
||||||
login → use JWT
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Blog/Project management:</strong> Create posts → add
|
|
||||||
comments/likes → upload images via S3
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<strong>Lineage game data:</strong> Fetch JSON data → register
|
|
||||||
character → find PvP opponents
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="border-rosewater bg-rosewater mt-4 rounded border p-4">
|
|
||||||
<p class="text-crust text-sm">
|
|
||||||
<strong>Note:</strong> Some endpoints require specific setup
|
|
||||||
(e.g., OAuth codes, existing database records, valid S3 keys).
|
|
||||||
Check the sample input to understand what data each endpoint
|
|
||||||
expects.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</main>
|
</Show>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user