Add REST API for quotes, shots, assets and tasks
Adds a key-authenticated REST API at /api/v1 so another system can create and manage quotes without going through the UI. Endpoints cover quotes (list, create, read, update, delete, recalculate), shots, assets and line items, plus read-only clients and rate cards. POST /api/v1/quotes builds a whole priced quote -- client, shots, assets and tasks -- in a single transaction. Routes are also mounted under /api/v1/jobs, since a quote and a job are the same record here. Keys are stored as SHA-256 with a display prefix, so the plaintext is shown once at creation and is not recoverable. They carry read/write scopes, can be revoked (effective on the next request), and record when they were last used. Minting and revoking live in Settings and are restricted to signed-in admins. /api/v1 is exempt from the session proxy because it authenticates with a bearer key rather than a cookie -- without this, every API call was redirected to /login as a 307. It is not unprotected: each route handler requires a live, unrevoked key with the right scope. Shot numbering and shot-code construction move into lib/shot-codes.ts so the UI and the API cannot drift. This also fixes numbering restarting at 0010 when a scene was entered in a different case to the stored one: the lookup upper-cased the scene but the stored value was left as typed. Unspecified currency and markup/tax/discount on an API-created quote fall back to the studio's configured quote defaults. Decimal fields are serialised as strings to preserve the exact precision the app's decimal arithmetic maintains. Note: this needs `prisma migrate deploy` for the new api_keys table. Settings will error for admins until that runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "api_keys" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"prefix" TEXT NOT NULL,
|
||||
"hash" TEXT NOT NULL,
|
||||
"scopes" TEXT[] DEFAULT ARRAY['read', 'write']::TEXT[],
|
||||
"lastUsedAt" TIMESTAMP(3),
|
||||
"expiresAt" TIMESTAMP(3),
|
||||
"revokedAt" TIMESTAMP(3),
|
||||
"createdById" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "api_keys_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "api_keys_prefix_key" ON "api_keys"("prefix");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "api_keys_hash_key" ON "api_keys"("hash");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "api_keys_revokedAt_idx" ON "api_keys"("revokedAt");
|
||||
Reference in New Issue
Block a user