[studio] Complete editor uploads and queued cloud builds (#135)

* [studio] Complete editor uploads and queued cloud builds

* [studio] Protect unpublished source and remove unused notification RPC
This commit is contained in:
dukedotdev
2026-10-19 11:04:58 -04:00
committed by GitHub
parent 81c372135c
commit a3291bc9ce
30 changed files with 2553 additions and 142 deletions
+54
View File
@@ -4756,6 +4756,59 @@ describe('public endpoints', () => {
})
})
describe('POST /api/sanitize/v2/isAllowed/bulk', () => {
const bulk = async (body: URLSearchParams | FormData, authed = true) =>
exports.default.fetch(`${ORIGIN}/api/sanitize/v2/isAllowed/bulk`, {
method: 'POST',
headers: authed ? await bearer('42') : {},
body,
})
test('401s without a token', async () => {
expect((await bulk(new URLSearchParams('Values=hello'), false)).status).toBe(401)
})
test('preserves repeated values, order, empty text and duplicates in the Studio envelope', async () => {
const body = new URLSearchParams()
for (const text of ['MakerRoom', 'fuck this', '', 'Scunthorpe', 'MakerRoom', 'sh1t'])
body.append('Values', text)
const res = await bulk(body)
expect(res.status).toBe(200)
expect(await res.json()).toEqual({
Success: true,
Error: null,
Value: { ArePure: [true, false, true, true, true, false] },
})
})
test('accepts a single multipart value and an empty batch', async () => {
const body = new FormData()
body.append('Values', 'a$$hole')
expect(await (await bulk(body)).json()).toEqual({
Success: true,
Error: null,
Value: { ArePure: [false] },
})
expect(await (await bulk(new URLSearchParams())).json()).toEqual({
Success: true,
Error: null,
Value: { ArePure: [] },
})
})
test('rejects file values rather than marking them clean', async () => {
const body = new FormData()
body.append('Values', new Blob(['hello']), 'text.txt')
const res = await bulk(body)
expect(res.status).toBe(400)
expect(await res.json()).toEqual({
Success: false,
Error: 'Values must be strings.',
Value: null,
})
})
})
describe('POST /api/sanitize/v1/isPure', () => {
const isPure = async (Value?: string, authed = true) =>
exports.default.fetch(`${ORIGIN}/api/sanitize/v1/isPure`, {
@@ -10343,6 +10396,7 @@ describe('openapi', () => {
'POST /api/rooms/v1/verifyRole',
'POST /api/sanitize/v1',
'POST /api/sanitize/v1/isPure',
'POST /api/sanitize/v2/isAllowed/bulk',
'POST /api/v1/progression/bulk',
'POST /outfits/bulk',
'POST /statsigUserProperties',
@@ -0,0 +1,52 @@
import { adminSecretsStore, env, SELF } from 'cloudflare:test'
import { beforeAll, expect, it } from 'vitest'
import { generateStudioBuildValidationToken, validateAndGetAccountId } from '@repo/jwt'
import type { Env } from '../../context'
declare module 'cloudflare:test' {
interface ProvidedEnv extends Env {}
}
beforeAll(async () => {
await adminSecretsStore(env.JWT_SECRET).create('test-key')
})
it('allows build validation credentials to check text without granting an account identity', async () => {
const token = await generateStudioBuildValidationToken('123456', 'test-key')
const headers = { Authorization: 'Bearer ' + token }
expect(
await validateAndGetAccountId(new Request('https://example.com', { headers }), 'test-key')
).toBeNull()
const response = await SELF.fetch('https://example.com/api/sanitize/v2/isAllowed/bulk', {
method: 'POST',
headers,
body: new URLSearchParams('Values=hello&Values=fuck'),
})
expect(response.status).toBe(200)
expect(await response.json()).toEqual({
Success: true,
Error: null,
Value: { ArePure: [true, false] },
})
expect(
(
await SELF.fetch('https://example.com/api/PlayerCheer/v1/create', {
method: 'POST',
headers,
body: new URLSearchParams(),
})
).status
).toBe(401)
})
it('rejects an invalid build validation signature', async () => {
const token = await generateStudioBuildValidationToken('123456', 'wrong-key')
expect(
(
await SELF.fetch('https://example.com/api/sanitize/v2/isAllowed/bulk', {
method: 'POST',
headers: { Authorization: 'Bearer ' + token },
body: new URLSearchParams('Values=hello'),
})
).status
).toBe(401)
})