fix: nixclient SSL calls correct user-scoped route, not admin endpoint
- Add /api/nixclient/ssl (GET) — returns certs for authenticated user only - Add /api/nixclient/ssl/:id/renew (POST) — validates cert belongs to user - Register sslRoutes in nixclient index.ts - nixclient SSL.tsx was calling /nixserver/ssl (requireAdminOrReseller) which would always 401 for regular users — fixed to /nixclient/ssl
This commit is contained in:
@@ -10,14 +10,14 @@ export default function SSL() {
|
|||||||
|
|
||||||
const fetch = async () => {
|
const fetch = async () => {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try { const r = await api.get('/nixserver/ssl'); setCerts(r.data.data) }
|
try { const r = await api.get('/nixclient/ssl'); setCerts(r.data.data) }
|
||||||
finally { setLoading(false) }
|
finally { setLoading(false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => { fetch() }, [])
|
useEffect(() => { fetch() }, [])
|
||||||
|
|
||||||
const renew = async (id: number) => {
|
const renew = async (id: number) => {
|
||||||
try { await api.post(`/nixserver/ssl/${id}/renew`); fetch() }
|
try { await api.post(`/nixclient/ssl/${id}/renew`); fetch() }
|
||||||
catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Renewal failed') }
|
catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Renewal failed') }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import domainRoutes from './domains.js'
|
|||||||
import ftpRoutes from './ftp.js'
|
import ftpRoutes from './ftp.js'
|
||||||
import cronRoutes from './cron.js'
|
import cronRoutes from './cron.js'
|
||||||
import statsRoutes from './stats.js'
|
import statsRoutes from './stats.js'
|
||||||
|
import sslRoutes from './ssl.js'
|
||||||
|
|
||||||
export default async function nixclientRoutes(fastify: FastifyInstance) {
|
export default async function nixclientRoutes(fastify: FastifyInstance) {
|
||||||
fastify.register(fileRoutes, { prefix: '/files' })
|
fastify.register(fileRoutes, { prefix: '/files' })
|
||||||
@@ -15,4 +16,5 @@ export default async function nixclientRoutes(fastify: FastifyInstance) {
|
|||||||
fastify.register(ftpRoutes, { prefix: '/ftp' })
|
fastify.register(ftpRoutes, { prefix: '/ftp' })
|
||||||
fastify.register(cronRoutes, { prefix: '/cron' })
|
fastify.register(cronRoutes, { prefix: '/cron' })
|
||||||
fastify.register(statsRoutes, { prefix: '/stats' })
|
fastify.register(statsRoutes, { prefix: '/stats' })
|
||||||
|
fastify.register(sslRoutes, { prefix: '/ssl' })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import type { FastifyInstance } from 'fastify'
|
||||||
|
import prisma from '../../db/client.js'
|
||||||
|
import { requireAuth } from '../../middleware/auth.js'
|
||||||
|
import { exec } from '../../core/exec.js'
|
||||||
|
|
||||||
|
export default async function sslRoutes(fastify: FastifyInstance) {
|
||||||
|
const preHandler = [requireAuth]
|
||||||
|
|
||||||
|
// GET /api/nixclient/ssl — certs for the authenticated user's account only
|
||||||
|
fastify.get('/', { preHandler }, async (request, reply) => {
|
||||||
|
const user = request.user!
|
||||||
|
const accountId = user.sub
|
||||||
|
|
||||||
|
const certs = await prisma.sslCertificate.findMany({
|
||||||
|
where: { accountId },
|
||||||
|
orderBy: { createdAt: 'desc' },
|
||||||
|
})
|
||||||
|
return reply.send({ success: true, data: certs })
|
||||||
|
})
|
||||||
|
|
||||||
|
// POST /api/nixclient/ssl/:id/renew
|
||||||
|
fastify.post('/:id/renew', { preHandler }, async (request, reply) => {
|
||||||
|
const { id } = request.params as { id: string }
|
||||||
|
const user = request.user!
|
||||||
|
|
||||||
|
const cert = await prisma.sslCertificate.findFirst({
|
||||||
|
where: { id: parseInt(id, 10), accountId: user.sub },
|
||||||
|
})
|
||||||
|
if (!cert) return reply.code(404).send({ success: false, error: 'Certificate not found' })
|
||||||
|
|
||||||
|
const result = await exec('certbot', ['renew', '--cert-name', cert.domain, '--non-interactive'])
|
||||||
|
if (result.exitCode !== 0) {
|
||||||
|
return reply.code(500).send({ success: false, error: `Renewal failed: ${result.stderr}` })
|
||||||
|
}
|
||||||
|
|
||||||
|
const expiresAt = new Date()
|
||||||
|
expiresAt.setDate(expiresAt.getDate() + 90)
|
||||||
|
|
||||||
|
const updated = await prisma.sslCertificate.update({
|
||||||
|
where: { id: cert.id },
|
||||||
|
data: { status: 'active', issuedAt: new Date(), expiresAt },
|
||||||
|
})
|
||||||
|
|
||||||
|
return reply.send({ success: true, data: updated })
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user