495 lines
16 KiB
JavaScript
495 lines
16 KiB
JavaScript
const express = require('express');
|
|
const { certificateController } = require('../modules/certificate');
|
|
const { verifyJWT } = require('../middleware/verifyJWT');
|
|
const isAdmin = require('../middleware/isAdmin');
|
|
const isMentorOrAdmin = require('../middleware/isMentorOrAdmin');
|
|
const multer = require('../middleware/multer');
|
|
const { multerErrorHandler, checkFileSizes } = require('../middleware/multer');
|
|
|
|
const router = express.Router();
|
|
|
|
/**
|
|
* @swagger
|
|
* components:
|
|
* schemas:
|
|
* Certificate:
|
|
* type: object
|
|
* properties:
|
|
* id:
|
|
* type: integer
|
|
* example: 1
|
|
* id_project:
|
|
* type: integer
|
|
* example: 2
|
|
* id_user:
|
|
* type: integer
|
|
* example: 5
|
|
* certificate_no:
|
|
* type: string
|
|
* example: "CERT/20260609/PRJ2/USR5"
|
|
* issued_at:
|
|
* type: string
|
|
* format: date-time
|
|
* example: "2026-06-09T14:00:00.000Z"
|
|
* user:
|
|
* type: object
|
|
* properties:
|
|
* id:
|
|
* type: integer
|
|
* example: 5
|
|
* full_name:
|
|
* type: string
|
|
* example: "Rafi Athallah"
|
|
* email:
|
|
* type: string
|
|
* example: "rafi@student.com"
|
|
* project:
|
|
* type: object
|
|
* properties:
|
|
* id:
|
|
* type: integer
|
|
* example: 2
|
|
* project_name:
|
|
* type: string
|
|
* example: "Internify Platform Dev"
|
|
* description:
|
|
* type: string
|
|
* example: "Project to develop features of the Internify web app"
|
|
* start_date:
|
|
* type: string
|
|
* format: date
|
|
* example: "2026-07-10"
|
|
* end_date:
|
|
* type: string
|
|
* format: date
|
|
* example: "2026-08-10"
|
|
* CertificateClaimRequest:
|
|
* type: object
|
|
* required:
|
|
* - id_project
|
|
* properties:
|
|
* id_project:
|
|
* type: integer
|
|
* example: 2
|
|
*/
|
|
|
|
/**
|
|
* @swagger
|
|
* /certificate-api/claim:
|
|
* post:
|
|
* summary: Claim certificate for a completed project
|
|
* description: Interns can claim a certificate for a project once they have submitted all assigned tasks.
|
|
* tags: [Certificate]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* $ref: '#/components/schemas/CertificateClaimRequest'
|
|
* responses:
|
|
* 201:
|
|
* description: Certificate claimed successfully
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: boolean
|
|
* example: true
|
|
* data:
|
|
* $ref: '#/components/schemas/Certificate'
|
|
* message:
|
|
* type: string
|
|
* example: "Certificate claimed successfully"
|
|
* code:
|
|
* type: integer
|
|
* example: 201
|
|
* 400:
|
|
* description: Bad request (no tasks assigned or not all tasks submitted)
|
|
* 401:
|
|
* description: Unauthorized
|
|
* 403:
|
|
* description: Forbidden (only interns can claim, or not a member of project)
|
|
* 404:
|
|
* description: Project not found
|
|
* 409:
|
|
* description: Conflict (certificate already claimed)
|
|
* 500:
|
|
* description: Internal server error
|
|
*/
|
|
router.post('/claim', verifyJWT, certificateController.claimCertificate);
|
|
|
|
/**
|
|
* @swagger
|
|
* /certificate-api/generate:
|
|
* post:
|
|
* summary: Batch generate certificates (Admin/Mentor only)
|
|
* description: Mentors or Admins can batch-generate certificates for selected eligible interns of a project.
|
|
* tags: [Certificate]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* required:
|
|
* - id_project
|
|
* - id_users
|
|
* properties:
|
|
* id_project:
|
|
* type: integer
|
|
* example: 2
|
|
* id_users:
|
|
* type: array
|
|
* items:
|
|
* type: integer
|
|
* example: [5, 6]
|
|
* responses:
|
|
* 201:
|
|
* description: Certificates generated successfully
|
|
* 400:
|
|
* description: Bad request (not eligible or missing parameters)
|
|
* 401:
|
|
* description: Unauthorized
|
|
* 403:
|
|
* description: Forbidden (only mentors/admins of the project can generate)
|
|
* 409:
|
|
* description: Conflict (certificate already generated for one or more interns)
|
|
* 500:
|
|
* description: Internal server error
|
|
*/
|
|
router.post('/generate', verifyJWT, isMentorOrAdmin, certificateController.generateCertificates);
|
|
|
|
|
|
/**
|
|
* @swagger
|
|
* /certificate-api/my-certificates:
|
|
* get:
|
|
* summary: Get logged-in intern's certificates
|
|
* description: Retrieve all certificates earned by the currently logged-in intern.
|
|
* tags: [Certificate]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: Certificates retrieved successfully
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: boolean
|
|
* example: true
|
|
* data:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Certificate'
|
|
* message:
|
|
* type: string
|
|
* example: "Certificates retrieved successfully"
|
|
* code:
|
|
* type: integer
|
|
* example: 200
|
|
* 401:
|
|
* description: Unauthorized
|
|
* 403:
|
|
* description: Forbidden (only interns can access this)
|
|
* 500:
|
|
* description: Internal server error
|
|
*/
|
|
router.get('/my-certificates', verifyJWT, certificateController.getMyCertificates);
|
|
|
|
/**
|
|
* @swagger
|
|
* /certificate-api/all:
|
|
* get:
|
|
* summary: Get all issued certificates (Admin only)
|
|
* description: Admin/Mentor can retrieve all certificates issued across the system.
|
|
* tags: [Certificate]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: All certificates retrieved successfully
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: boolean
|
|
* example: true
|
|
* data:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Certificate'
|
|
* message:
|
|
* type: string
|
|
* example: "All certificates retrieved successfully"
|
|
* code:
|
|
* type: integer
|
|
* example: 200
|
|
* 401:
|
|
* description: Unauthorized
|
|
* 403:
|
|
* description: Forbidden (Admin only)
|
|
* 500:
|
|
* description: Internal server error
|
|
*/
|
|
router.get('/all', verifyJWT, isAdmin, certificateController.getAllCertificates);
|
|
|
|
/**
|
|
* @swagger
|
|
* /certificate-api/detail/{id}:
|
|
* get:
|
|
* summary: Get certificate detail
|
|
* description: Fetch detailed information for a certificate by its ID. Interns can only access their own. Admins can access any.
|
|
* tags: [Certificate]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* schema:
|
|
* type: integer
|
|
* required: true
|
|
* description: Certificate ID
|
|
* example: 1
|
|
* responses:
|
|
* 200:
|
|
* description: Certificate details retrieved successfully
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: boolean
|
|
* example: true
|
|
* data:
|
|
* $ref: '#/components/schemas/Certificate'
|
|
* message:
|
|
* type: string
|
|
* example: "Certificate details retrieved successfully"
|
|
* code:
|
|
* type: integer
|
|
* example: 200
|
|
* 401:
|
|
* description: Unauthorized
|
|
* 403:
|
|
* description: Forbidden (Accessing another user's certificate)
|
|
* 404:
|
|
* description: Certificate not found
|
|
* 500:
|
|
* description: Internal server error
|
|
*/
|
|
router.get('/detail/:id', verifyJWT, certificateController.getCertificateDetail);
|
|
|
|
/**
|
|
* @swagger
|
|
* /certificate-api/project/{id_project}:
|
|
* get:
|
|
* summary: Get certificates issued for a specific project (Admin/Mentor only)
|
|
* description: Admin/Mentor can retrieve all certificates issued to interns for a specific project.
|
|
* tags: [Certificate]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id_project
|
|
* schema:
|
|
* type: integer
|
|
* required: true
|
|
* description: Project ID
|
|
* example: 2
|
|
* responses:
|
|
* 200:
|
|
* description: Project certificates retrieved successfully
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: boolean
|
|
* example: true
|
|
* data:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Certificate'
|
|
* message:
|
|
* type: string
|
|
* example: "Project certificates retrieved successfully"
|
|
* code:
|
|
* type: integer
|
|
* example: 200
|
|
* 401:
|
|
* description: Unauthorized
|
|
* 403:
|
|
* description: Forbidden (Admin/Mentor only)
|
|
* 500:
|
|
* description: Internal server error
|
|
*/
|
|
router.get('/project/:id_project', verifyJWT, isMentorOrAdmin, certificateController.getProjectCertificates);
|
|
/**
|
|
* @swagger
|
|
* /certificate-api/verify-uuid/{uuid}:
|
|
* get:
|
|
* summary: Verify a certificate by UUID (Public)
|
|
* description: Verify the validity of a certificate by its unique UUID for the frontend. Returns intern's name, creation date, and UUID.
|
|
* tags: [Certificate]
|
|
* parameters:
|
|
* - in: path
|
|
* name: uuid
|
|
* schema:
|
|
* type: string
|
|
* format: uuid
|
|
* required: true
|
|
* description: The certificate UUID to verify
|
|
* example: "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
|
|
* responses:
|
|
* 200:
|
|
* description: Certificate is valid
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: boolean
|
|
* example: true
|
|
* data:
|
|
* type: object
|
|
* properties:
|
|
* uuid:
|
|
* type: string
|
|
* example: "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
|
|
* intern_name:
|
|
* type: string
|
|
* example: "Rafi Athallah"
|
|
* project:
|
|
* type: object
|
|
* properties:
|
|
* id:
|
|
* type: integer
|
|
* example: 2
|
|
* project_name:
|
|
* type: string
|
|
* example: "Internify Platform Dev"
|
|
* description:
|
|
* type: string
|
|
* example: "Project to develop features of the Internify web app"
|
|
* start_date:
|
|
* type: string
|
|
* format: date
|
|
* example: "2026-07-10"
|
|
* end_date:
|
|
* type: string
|
|
* format: date
|
|
* example: "2026-08-10"
|
|
* created_at:
|
|
* type: string
|
|
* format: date-time
|
|
* example: "2026-06-09T14:00:00.000Z"
|
|
* message:
|
|
* type: string
|
|
* example: "Certificate validated successfully"
|
|
* code:
|
|
* type: integer
|
|
* example: 200
|
|
* 400:
|
|
* description: Bad request (missing UUID)
|
|
* 404:
|
|
* description: Certificate not found or invalid
|
|
* 500:
|
|
* description: Internal server error
|
|
*/
|
|
router.get('/verify-uuid/:uuid', certificateController.verifyCertificateByUuid);
|
|
|
|
/**
|
|
* @swagger
|
|
* /certificate-api/projects/{id_project}/template:
|
|
* post:
|
|
* summary: Upload certificate template for a project
|
|
* description: Admin or Mentor can upload a certificate template file (image/pdf) for a specific project. Mentors can only upload to projects they own.
|
|
* tags: [Certificate]
|
|
* security:
|
|
* - bearerAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id_project
|
|
* schema:
|
|
* type: integer
|
|
* required: true
|
|
* description: The ID of the project to associate the template with
|
|
* example: 1
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* multipart/form-data:
|
|
* schema:
|
|
* type: object
|
|
* required:
|
|
* - template
|
|
* properties:
|
|
* template:
|
|
* type: string
|
|
* format: binary
|
|
* description: The certificate template file (JPEG, JPG, PNG, or PDF). Max size 5MB.
|
|
* responses:
|
|
* 200:
|
|
* description: Certificate template uploaded successfully
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: boolean
|
|
* example: true
|
|
* data:
|
|
* type: object
|
|
* properties:
|
|
* id_project:
|
|
* type: integer
|
|
* example: 1
|
|
* certificate_template:
|
|
* type: string
|
|
* example: "/uploads/1718000000000-987654321.png"
|
|
* message:
|
|
* type: string
|
|
* example: "Certificate template uploaded successfully"
|
|
* code:
|
|
* type: integer
|
|
* example: 200
|
|
* 400:
|
|
* description: Bad request (missing file or invalid input)
|
|
* 401:
|
|
* description: Unauthorized
|
|
* 403:
|
|
* description: Forbidden (Mentor does not own the project, or unauthorized role)
|
|
* 404:
|
|
* description: Project not found
|
|
* 413:
|
|
* description: File size too large (max 5MB)
|
|
* 500:
|
|
* description: Internal server error
|
|
*/
|
|
router.post(
|
|
'/projects/:id_project/template',
|
|
verifyJWT,
|
|
isMentorOrAdmin,
|
|
multer.single('template'),
|
|
checkFileSizes,
|
|
multerErrorHandler,
|
|
certificateController.uploadCertificateTemplate
|
|
);
|
|
|
|
module.exports = router;
|