142 lines
3.2 KiB
TypeScript
142 lines
3.2 KiB
TypeScript
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<JobRow[]>(
|
|
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<void> {
|
|
|
|
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!',
|
|
|
|
});
|
|
})
|
|
}
|