feat: add admin accounts and image templates

This commit is contained in:
inman
2026-07-03 11:25:25 +08:00
parent d98e58adfa
commit c3ea9f0eb1
61 changed files with 7016 additions and 199 deletions

View File

@@ -1,9 +1,9 @@
import { createAsset } from "@/lib/server/data-store";
import { jsonOk, readJsonBody } from "@/lib/server/api";
import { authenticatePublicApiRequest } from "@/lib/server/public-api-auth";
import { authenticatePublicApiRequest, publicApiOwnerId } from "@/lib/server/public-api-auth";
import { listPublicApiAssets } from "@/lib/server/public-api-assets";
import { publicApiError } from "@/lib/server/public-api-response";
import { DEFAULT_OWNER_ID, requestOrigin } from "@/lib/server/runtime";
import { requestOrigin } from "@/lib/server/runtime";
import { saveUploadAsset } from "@/lib/server/storage";
import type { AssetKind } from "@/lib/types";
@@ -21,13 +21,14 @@ export async function GET(request: Request) {
export async function POST(request: Request) {
try {
const client = authenticatePublicApiRequest(request);
const ownerId = publicApiOwnerId(client);
const contentType = request.headers.get("content-type") || "";
if (contentType.includes("multipart/form-data")) {
const form = await request.formData();
const files = form.getAll("files").filter((item): item is File => item instanceof File);
if (!files.length) throw new Error("No files uploaded.");
const assets = await Promise.all(files.map(async (file) => saveUploadAsset({
ownerId: DEFAULT_OWNER_ID,
ownerId,
bytes: await awaitFileBytes(file),
fileName: file.name,
contentType: file.type || "application/octet-stream",
@@ -45,7 +46,7 @@ export async function POST(request: Request) {
}>(request);
if (!body.url) throw new Error("url is required");
const asset = await createAsset({
ownerId: DEFAULT_OWNER_ID,
ownerId,
kind: body.kind || "image",
name: body.name || "外部素材",
url: body.url,

View File

@@ -1,6 +1,6 @@
import { clearGenerationJobLock, getGenerationJob, updateGenerationJob } from "@/lib/server/data-store";
import { jsonError, jsonOk } from "@/lib/server/api";
import { authenticatePublicApiRequest } from "@/lib/server/public-api-auth";
import { authenticatePublicApiRequest, publicApiOwnerId } from "@/lib/server/public-api-auth";
import { publicApiError } from "@/lib/server/public-api-response";
export const runtime = "nodejs";
@@ -10,7 +10,9 @@ export async function POST(request: Request, context: { params: Promise<{ id: st
const client = authenticatePublicApiRequest(request);
const { id } = await context.params;
const job = await getGenerationJob(id);
if (!job || job.externalClientId !== client.id) return jsonError("Job not found.", 404);
if (!job || job.ownerId !== publicApiOwnerId(client) || job.externalClientId !== client.id) {
return jsonError("Job not found.", 404);
}
if (["succeeded", "failed", "expired", "cancelled"].includes(job.status)) {
return jsonOk({ job });
}

View File

@@ -1,6 +1,6 @@
import { getGenerationJob } from "@/lib/server/data-store";
import { jsonError, jsonOk } from "@/lib/server/api";
import { authenticatePublicApiRequest } from "@/lib/server/public-api-auth";
import { authenticatePublicApiRequest, publicApiOwnerId } from "@/lib/server/public-api-auth";
import { publicApiError } from "@/lib/server/public-api-response";
export const runtime = "nodejs";
@@ -10,7 +10,9 @@ export async function GET(request: Request, context: { params: Promise<{ id: str
const client = authenticatePublicApiRequest(request);
const { id } = await context.params;
const job = await getGenerationJob(id);
if (!job || job.externalClientId !== client.id) return jsonError("Job not found.", 404);
if (!job || job.ownerId !== publicApiOwnerId(client) || job.externalClientId !== client.id) {
return jsonError("Job not found.", 404);
}
return jsonOk({ job });
} catch (error) {
return publicApiError(error);

View File

@@ -1,9 +1,9 @@
import { listGenerationJobsFiltered } from "@/lib/server/data-store";
import { jsonOk, readJsonBody } from "@/lib/server/api";
import { authenticatePublicApiRequest } from "@/lib/server/public-api-auth";
import { authenticatePublicApiRequest, publicApiOwnerId } from "@/lib/server/public-api-auth";
import { createPublicGenerationJob, type PublicJobCreateBody } from "@/lib/server/public-api-jobs";
import { publicApiError } from "@/lib/server/public-api-response";
import { DEFAULT_OWNER_ID, requestOrigin } from "@/lib/server/runtime";
import { requestOrigin } from "@/lib/server/runtime";
import type { GenerationCapability, GenerationStatus } from "@/lib/types";
export const runtime = "nodejs";
@@ -13,7 +13,7 @@ export async function GET(request: Request) {
const client = authenticatePublicApiRequest(request);
const url = new URL(request.url);
const jobs = await listGenerationJobsFiltered({
ownerId: DEFAULT_OWNER_ID,
ownerId: publicApiOwnerId(client),
externalClientId: client.id,
status: parseStatus(url.searchParams.get("status")),
capability: parseCapability(url.searchParams.get("capability")),

View File

@@ -50,6 +50,7 @@ export async function GET(request: Request) {
required: ["id", "capability", "provider", "status", "createdAt", "updatedAt"],
properties: {
id: { type: "string", example: "job_mpqe3wtt_12ed738079" },
ownerId: { type: "string", example: "api:partner-a" },
externalClientId: { type: "string" },
capability: { $ref: "#/components/schemas/GenerationCapability" },
provider: { type: "string", enum: ["volcengine-visual", "evolink", "seedance", "mock"] },