feat: certification rules, content sanitization, handle draft course updates and reset content, better redis logging

This commit is contained in:
Rotimi Best
2026-03-30 08:24:55 +01:00
parent ff2ad59377
commit 5a8f50f67b
131 changed files with 5643 additions and 2134 deletions
+32
View File
@@ -26,6 +26,7 @@ import {
getCourseProgress,
updateCourse
} from '@api/services/course/course';
import { assertCertificateDownloadAllowed, evaluateCourseCertification } from '@api/services/course/completion';
import { getCourseTags, replaceCourseTags } from '@api/services/tag';
import { Hono } from '@api/utils/hono';
@@ -393,6 +394,33 @@ export const courseRouter = new Hono()
}
}
)
/**
* GET /course/:courseId/certification-evaluation
* Full certification eligibility for the current user (blockers for UI).
*/
.get(
'/:courseId/certification-evaluation',
authMiddleware,
courseMemberMiddleware,
zValidator('param', ZCourseProgressParam),
async (c) => {
try {
const { courseId } = c.req.valid('param');
const user = c.get('user')!;
const data = await evaluateCourseCertification(courseId, user.id);
return c.json(
{
success: true,
data
},
200
);
} catch (error) {
return handleError(c, error, 'Failed to evaluate certification');
}
}
)
/**
* GET /course/:courseId/analytics
* Gets course analytics including student progress, completion rates, and grades
@@ -427,6 +455,10 @@ export const courseRouter = new Hono()
zValidator('param', ZCourseDownloadParam),
zValidator('json', ZCertificateDownload),
async (c) => {
const { courseId } = c.req.valid('param');
const user = c.get('user')!;
await assertCertificateDownloadAllowed(courseId, user.id);
const validatedData = c.req.valid('json');
const result = await generateCertificate(validatedData);