feat: add clientApiKey per-app for mobile bug submission

This commit is contained in:
2026-04-30 13:50:29 +08:00
parent 4e9d5964ae
commit 40a5f38eaf
4 changed files with 98 additions and 5 deletions

View File

@@ -377,6 +377,7 @@ export function createApp() {
maintenance: app.maintenance,
active: app.active,
urlApi: app.urlApi,
hasClientApiKey: !!app.clientApiKey,
}))
}, {
query: t.Object({
@@ -491,6 +492,20 @@ export function createApp() {
detail: { summary: 'Activate App', tags: ['Apps'] },
})
.post('/api/apps/:appId/generate-key', async ({ params: { appId }, request, set }) => {
const auth = await requireDeveloper(request, set)
if (!auth) return { error: set.status === 401 ? 'Unauthorized' : 'Forbidden' }
const app = await prisma.app.findUnique({ where: { id: appId } })
if (!app) { set.status = 404; return { error: 'App not found' } }
const key = `mapp_${Buffer.from(crypto.getRandomValues(new Uint8Array(24))).toString('hex')}`
await prisma.app.update({ where: { id: appId }, data: { clientApiKey: key } })
await createSystemLog(auth.userId, 'UPDATE', `Generated client API key for app: ${appId}`)
return { clientApiKey: key }
}, {
params: t.Object({ appId: t.String() }),
detail: { summary: 'Generate Client API Key', tags: ['Apps'] },
})
// ─── Logs API ──────────────────────────────────────
.get('/api/logs', async ({ query }) => {
const page = Number(query.page) || 1
@@ -854,10 +869,21 @@ export function createApp() {
})
.post('/api/bugs', async ({ body, request, set }) => {
const auth = await checkAuth(request)
let auth = await checkAuth(request)
if (!auth) {
const xKey = request.headers.get('x-api-key')
const appId = (body as any).app
if (xKey && appId) {
const app = await prisma.app.findUnique({ where: { id: appId, active: true } })
if (app?.clientApiKey && app.clientApiKey === xKey) {
const developer = await prisma.user.findFirst({ where: { role: 'DEVELOPER' } })
if (developer) auth = { actingUserId: developer.id, reporterUserId: null, isApiKey: true }
}
}
}
if (!auth) {
set.status = 401
return { error: 'Unauthorized: sertakan session cookie atau header X-API-Key' }
return { error: 'Unauthorized: provide session cookie or valid X-API-Key' }
}
const { actingUserId, reporterUserId, isApiKey } = auth