119 lines
4.6 KiB
JavaScript
119 lines
4.6 KiB
JavaScript
import { prisma } from '../../lib/prisma.js'
|
|
|
|
function validateBlockPayload(body, reply) {
|
|
const key = String(body?.key || '').trim()
|
|
const title = String(body?.title || '').trim()
|
|
const content = String(body?.body || '').trim()
|
|
const sort = Number(body?.sort ?? 0)
|
|
const published = body?.published === undefined ? true : Boolean(body.published)
|
|
|
|
if (!key) return reply.code(400).send({ error: 'key обязателен' })
|
|
if (!/^[a-z0-9_-]{2,60}$/i.test(key)) {
|
|
return reply.code(400).send({ error: 'key должен быть 2-60 символов: буквы, цифры, "_" или "-"' })
|
|
}
|
|
if (!title) return reply.code(400).send({ error: 'title обязателен' })
|
|
if (title.length > 120) return reply.code(400).send({ error: 'title максимум 120 символов' })
|
|
if (!content) return reply.code(400).send({ error: 'body обязателен' })
|
|
if (content.length > 5000) return reply.code(400).send({ error: 'body максимум 5000 символов' })
|
|
if (!Number.isFinite(sort) || Math.abs(sort) > 10_000) return reply.code(400).send({ error: 'Некорректный sort' })
|
|
|
|
return { key, title, body: content, sort: Math.trunc(sort), published }
|
|
}
|
|
|
|
export async function registerInfoPageRoutes(fastify) {
|
|
fastify.get('/api/info-page/blocks', async () => {
|
|
const items = await prisma.infoPageBlock.findMany({
|
|
where: { published: true },
|
|
orderBy: [{ sort: 'asc' }, { createdAt: 'asc' }],
|
|
})
|
|
return { items }
|
|
})
|
|
|
|
fastify.get(
|
|
'/api/admin/info-page/blocks',
|
|
{ preHandler: [fastify.verifyAdmin] },
|
|
async () => {
|
|
const items = await prisma.infoPageBlock.findMany({ orderBy: [{ sort: 'asc' }, { createdAt: 'asc' }] })
|
|
return { items }
|
|
},
|
|
)
|
|
|
|
fastify.post(
|
|
'/api/admin/info-page/blocks',
|
|
{ preHandler: [fastify.verifyAdmin] },
|
|
async (request, reply) => {
|
|
const validated = validateBlockPayload(request.body, reply)
|
|
if (!validated) return
|
|
|
|
try {
|
|
const item = await prisma.infoPageBlock.create({ data: validated })
|
|
return reply.code(201).send({ item })
|
|
} catch {
|
|
return reply.code(409).send({ error: 'Блок с таким key уже существует' })
|
|
}
|
|
},
|
|
)
|
|
|
|
fastify.patch(
|
|
'/api/admin/info-page/blocks/:id',
|
|
{ preHandler: [fastify.verifyAdmin] },
|
|
async (request, reply) => {
|
|
const { id } = request.params
|
|
const existing = await prisma.infoPageBlock.findUnique({ where: { id } })
|
|
if (!existing) return reply.code(404).send({ error: 'Блок не найден' })
|
|
|
|
const body = request.body ?? {}
|
|
const data = {}
|
|
if (body.key !== undefined) {
|
|
const key = String(body.key || '').trim()
|
|
if (!key) return reply.code(400).send({ error: 'key обязателен' })
|
|
if (!/^[a-z0-9_-]{2,60}$/i.test(key)) {
|
|
return reply.code(400).send({ error: 'key должен быть 2-60 символов: буквы, цифры, "_" или "-"' })
|
|
}
|
|
data.key = key
|
|
}
|
|
if (body.title !== undefined) {
|
|
const title = String(body.title || '').trim()
|
|
if (!title) return reply.code(400).send({ error: 'title обязателен' })
|
|
if (title.length > 120) return reply.code(400).send({ error: 'title максимум 120 символов' })
|
|
data.title = title
|
|
}
|
|
if (body.body !== undefined) {
|
|
const content = String(body.body || '').trim()
|
|
if (!content) return reply.code(400).send({ error: 'body обязателен' })
|
|
if (content.length > 5000) return reply.code(400).send({ error: 'body максимум 5000 символов' })
|
|
data.body = content
|
|
}
|
|
if (body.sort !== undefined) {
|
|
const sort = Number(body.sort)
|
|
if (!Number.isFinite(sort) || Math.abs(sort) > 10_000) return reply.code(400).send({ error: 'Некорректный sort' })
|
|
data.sort = Math.trunc(sort)
|
|
}
|
|
if (body.published !== undefined) {
|
|
data.published = Boolean(body.published)
|
|
}
|
|
|
|
try {
|
|
const item = await prisma.infoPageBlock.update({ where: { id }, data })
|
|
return { item }
|
|
} catch {
|
|
return reply.code(409).send({ error: 'Блок с таким key уже существует' })
|
|
}
|
|
},
|
|
)
|
|
|
|
fastify.delete(
|
|
'/api/admin/info-page/blocks/:id',
|
|
{ preHandler: [fastify.verifyAdmin] },
|
|
async (request, reply) => {
|
|
const { id } = request.params
|
|
try {
|
|
await prisma.infoPageBlock.delete({ where: { id } })
|
|
return reply.code(204).send()
|
|
} catch {
|
|
return reply.code(404).send({ error: 'Блок не найден' })
|
|
}
|
|
},
|
|
)
|
|
}
|