import { PrismaClient, Prisma } from '../../generated/prisma' import { withAccelerate } from "@prisma/extension-accelerate" import { type FastifyInstance, type FastifyReply, type FastifyRequest } from 'fastify' import { env } from '../config/env' import { constants } from '../config/constants' import { isAdmin } from '../utils/privs' import { makeWorkerUtils, WorkerUtils } from 'graphile-worker' import logger from '../utils/logger' import { } from '../../generated/prisma' const prisma = new PrismaClient().$extends(withAccelerate()) interface JobRow { id: number; queue_name: string | null; task_identifier: string; priority: number; run_at: Date; attempts: number; max_attempts: number; last_error: string | null; created_at: Date; updated_at: Date; key: string | null; locked_at: Date | null; locked_by: string | null; revision: number; flags: string | null; } async function getJobs() { const jobs = await prisma.$queryRaw( Prisma.sql` SELECT id, queue_name, task_identifier, priority, run_at, attempts, max_attempts, last_error, created_at, updated_at, key, locked_at, locked_by, revision, flags FROM graphile_worker.jobs ORDER BY id DESC LIMIT 2500 ` ); return jobs; } export default async function adminRoutes(fastify: FastifyInstance): Promise { fastify.get('/admin', async function (request, reply) { const userId = request.session.get('userId'); if (!userId) { throw new Error('No user is logged in.'); } const user = await prisma.user.findUnique({ where: { id: userId }, include: { roles: true } }); if (!user) throw new Error('User not found.'); if (!isAdmin(user)) { return reply.status(403).send("you are not a jedi, yet"); } else { const jobs = await getJobs(); logger.debug(jobs[0]) return reply.viewAsync("admin.hbs", { jobs, user, site: constants.site, }, { layout: 'layouts/main.hbs' }); } }) fastify.delete('/admin/jobs', async function (request, reply) { const userId = request.session.get('userId') const user = await prisma.user.findUnique({ where: { id: userId }, include: { roles: true } }) if (!user) throw new Error('User not found.'); if (isAdmin(user)) { let workerUtils: WorkerUtils | undefined; try { const workerUtils = await makeWorkerUtils({ connectionString: env.DATABASE_URL }); const jobIdsResult = await prisma.$queryRaw<{ id: number }[]>( Prisma.sql`SELECT id FROM graphile_worker.jobs` ); const jobIds: string[] = jobIdsResult.map(j => '' + j.id); logger.warn(`Permanently failing all graphile-worker jobs on behalf of ${user.id}.`); if (jobIds.length > 0) { await workerUtils.permanentlyFailJobs(jobIds, 'Job deleted by admin'); } } finally { if (workerUtils) { await workerUtils.release(); } } } return reply.viewAsync("admin.hbs", { user, site: constants.site, notification: 'Jobs beleted!', }); }) }