Commit 66487b83 authored by Phạm Quang Bảo's avatar Phạm Quang Bảo

feat(challenge_8): authorization and add api get/set role

parent 11e8bbc6
...@@ -3,6 +3,8 @@ import type { Resource } from "express-automatic-routes"; ...@@ -3,6 +3,8 @@ import type { Resource } from "express-automatic-routes";
import { ClassesProvider } from "#providers/ClassesProvider"; import { ClassesProvider } from "#providers/ClassesProvider";
import { Req, Res } from "#interface/IApi"; import { Req, Res } from "#interface/IApi";
import queryModifier from "#middlewares/request"; import queryModifier from "#middlewares/request";
import { authorize } from "#middlewares/authorization";
import { authMiddleware } from "#middlewares/authentication";
export default (_express: Application) => { export default (_express: Application) => {
const classesProvider = new ClassesProvider(); const classesProvider = new ClassesProvider();
...@@ -13,6 +15,8 @@ export default (_express: Application) => { ...@@ -13,6 +15,8 @@ export default (_express: Application) => {
* /api/v1.0/classes: * /api/v1.0/classes:
* get: * get:
* tags: [Classes] * tags: [Classes]
* security:
* - bearerAuth: []
* parameters: * parameters:
* - $ref: '#/components/parameters/filters' * - $ref: '#/components/parameters/filters'
* - $ref: '#/components/parameters/sort' * - $ref: '#/components/parameters/sort'
...@@ -27,7 +31,7 @@ export default (_express: Application) => { ...@@ -27,7 +31,7 @@ export default (_express: Application) => {
* $ref: "#/components/schemas/ClassListResponse" * $ref: "#/components/schemas/ClassListResponse"
*/ */
get: { get: {
middleware: [queryModifier], middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
try { try {
...@@ -70,6 +74,8 @@ export default (_express: Application) => { ...@@ -70,6 +74,8 @@ export default (_express: Application) => {
* description: Lỗi hệ thống phía Server * description: Lỗi hệ thống phía Server
*/ */
post: { post: {
middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
try { try {
const newClass = await classesProvider.createClass(req.body); const newClass = await classesProvider.createClass(req.body);
......
...@@ -2,6 +2,9 @@ import type { Application } from "express"; ...@@ -2,6 +2,9 @@ import type { Application } from "express";
import type { Resource } from "express-automatic-routes"; import type { Resource } from "express-automatic-routes";
import { ClassesProvider } from "#providers/ClassesProvider.js"; import { ClassesProvider } from "#providers/ClassesProvider.js";
import { Req, Res } from "#interface/IApi"; import { Req, Res } from "#interface/IApi";
import { authorize } from "#middlewares/authorization";
import queryModifier from "#middlewares/request";
import { authMiddleware } from "#middlewares/authentication";
export default (_express: Application) => { export default (_express: Application) => {
const classesProvider = new ClassesProvider(); const classesProvider = new ClassesProvider();
...@@ -12,6 +15,8 @@ export default (_express: Application) => { ...@@ -12,6 +15,8 @@ export default (_express: Application) => {
* /api/v1.0/classes/{id}: * /api/v1.0/classes/{id}:
* get: * get:
* tags: [Classes] * tags: [Classes]
* security:
* - bearerAuth: []
* parameters: * parameters:
* - name: id * - name: id
* in: path * in: path
...@@ -28,6 +33,8 @@ export default (_express: Application) => { ...@@ -28,6 +33,8 @@ export default (_express: Application) => {
* $ref: "#/components/schemas/ClassResponse" * $ref: "#/components/schemas/ClassResponse"
*/ */
get: { get: {
middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
const { id } = req.params; const { id } = req.params;
...@@ -57,6 +64,8 @@ export default (_express: Application) => { ...@@ -57,6 +64,8 @@ export default (_express: Application) => {
* /api/v1.0/classes/{id}: * /api/v1.0/classes/{id}:
* put: * put:
* tags: [Classes] * tags: [Classes]
* security:
* - bearerAuth: []
* parameters: * parameters:
* - name: id * - name: id
* in: path * in: path
...@@ -80,6 +89,8 @@ export default (_express: Application) => { ...@@ -80,6 +89,8 @@ export default (_express: Application) => {
* $ref: "#/components/schemas/ClassResponse" * $ref: "#/components/schemas/ClassResponse"
*/ */
put: { put: {
middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
const { id } = req.params; const { id } = req.params;
...@@ -123,6 +134,8 @@ export default (_express: Application) => { ...@@ -123,6 +134,8 @@ export default (_express: Application) => {
* description: Xóa lớp học thành công * description: Xóa lớp học thành công
*/ */
delete: { delete: {
middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
const { id } = req.params; const { id } = req.params;
......
...@@ -2,6 +2,9 @@ import type { Application } from "express"; ...@@ -2,6 +2,9 @@ import type { Application } from "express";
import type { Resource } from "express-automatic-routes"; import type { Resource } from "express-automatic-routes";
import { CoursesProvider } from "#providers/CoursesProvider.js"; import { CoursesProvider } from "#providers/CoursesProvider.js";
import { Req, Res } from "#interface/IApi"; import { Req, Res } from "#interface/IApi";
import queryModifier from "#middlewares/request";
import { authorize } from "#middlewares/authorization";
import { authMiddleware } from "#middlewares/authentication";
export default (_express: Application) => { export default (_express: Application) => {
const coursesProvider = new CoursesProvider(); const coursesProvider = new CoursesProvider();
...@@ -12,6 +15,8 @@ export default (_express: Application) => { ...@@ -12,6 +15,8 @@ export default (_express: Application) => {
* /api/v1.0/courses: * /api/v1.0/courses:
* get: * get:
* tags: [Courses] * tags: [Courses]
* security:
* - bearerAuth: []
* parameters: * parameters:
* - $ref: '#/components/parameters/filters' * - $ref: '#/components/parameters/filters'
* - $ref: '#/components/parameters/sort' * - $ref: '#/components/parameters/sort'
...@@ -26,6 +31,8 @@ export default (_express: Application) => { ...@@ -26,6 +31,8 @@ export default (_express: Application) => {
* $ref: "#/components/schemas/CourseListResponse" * $ref: "#/components/schemas/CourseListResponse"
*/ */
get: { get: {
middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
try { try {
const courses = await coursesProvider.getAllCourses(req.payload); const courses = await coursesProvider.getAllCourses(req.payload);
...@@ -48,6 +55,8 @@ export default (_express: Application) => { ...@@ -48,6 +55,8 @@ export default (_express: Application) => {
* post: * post:
* tags: [Courses] * tags: [Courses]
* description: Thêm một khóa học mới vào hệ thống * description: Thêm một khóa học mới vào hệ thống
* security:
* - bearerAuth: []
* requestBody: * requestBody:
* required: true * required: true
* content: * content:
...@@ -63,6 +72,8 @@ export default (_express: Application) => { ...@@ -63,6 +72,8 @@ export default (_express: Application) => {
* $ref: "#/components/schemas/CourseResponse" * $ref: "#/components/schemas/CourseResponse"
*/ */
post: { post: {
middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
try { try {
const newCourse = await coursesProvider.createCourse(req.body); const newCourse = await coursesProvider.createCourse(req.body);
......
...@@ -2,6 +2,9 @@ import type { Application } from "express"; ...@@ -2,6 +2,9 @@ import type { Application } from "express";
import type { Resource } from "express-automatic-routes"; import type { Resource } from "express-automatic-routes";
import { CoursesProvider } from "#providers/CoursesProvider.js"; import { CoursesProvider } from "#providers/CoursesProvider.js";
import { Req, Res } from "#interface/IApi"; import { Req, Res } from "#interface/IApi";
import queryModifier from "#middlewares/request";
import { authorize } from "#middlewares/authorization";
import { authMiddleware } from "#middlewares/authentication";
export default (_express: Application) => { export default (_express: Application) => {
const coursesProvider = new CoursesProvider(); const coursesProvider = new CoursesProvider();
...@@ -12,6 +15,8 @@ export default (_express: Application) => { ...@@ -12,6 +15,8 @@ export default (_express: Application) => {
* /api/v1.0/courses/{id}: * /api/v1.0/courses/{id}:
* get: * get:
* tags: [Courses] * tags: [Courses]
* security:
* - bearerAuth: []
* parameters: * parameters:
* - name: id * - name: id
* in: path * in: path
...@@ -28,6 +33,8 @@ export default (_express: Application) => { ...@@ -28,6 +33,8 @@ export default (_express: Application) => {
* $ref: "#/components/schemas/CourseResponse" * $ref: "#/components/schemas/CourseResponse"
*/ */
get: { get: {
middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
const id = req.params.id; const id = req.params.id;
...@@ -49,6 +56,8 @@ export default (_express: Application) => { ...@@ -49,6 +56,8 @@ export default (_express: Application) => {
* /api/v1.0/courses/{id}: * /api/v1.0/courses/{id}:
* put: * put:
* tags: [Courses] * tags: [Courses]
* security:
* - bearerAuth: []
* parameters: * parameters:
* - name: id * - name: id
* in: path * in: path
...@@ -72,6 +81,8 @@ export default (_express: Application) => { ...@@ -72,6 +81,8 @@ export default (_express: Application) => {
* $ref: "#/components/schemas/CourseResponse" * $ref: "#/components/schemas/CourseResponse"
*/ */
put: { put: {
middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
const { id } = req.params; const { id } = req.params;
...@@ -101,6 +112,8 @@ export default (_express: Application) => { ...@@ -101,6 +112,8 @@ export default (_express: Application) => {
* /api/v1.0/courses/{id}: * /api/v1.0/courses/{id}:
* delete: * delete:
* tags: [Courses] * tags: [Courses]
* security:
* - bearerAuth: []
* parameters: * parameters:
* - name: id * - name: id
* in: path * in: path
...@@ -117,6 +130,8 @@ export default (_express: Application) => { ...@@ -117,6 +130,8 @@ export default (_express: Application) => {
* $ref: "#/components/schemas/CourseResponse" * $ref: "#/components/schemas/CourseResponse"
*/ */
delete: { delete: {
middleware: [queryModifier, authMiddleware, authorize('admin', 'instructor')],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
const { id } = req.params; const { id } = req.params;
......
...@@ -2,6 +2,7 @@ import type { Application } from "express"; ...@@ -2,6 +2,7 @@ import type { Application } from "express";
import type { Resource } from "express-automatic-routes"; import type { Resource } from "express-automatic-routes";
import { EnrollProvider } from "#providers/EnrollProvider.js"; import { EnrollProvider } from "#providers/EnrollProvider.js";
import { Req, Res } from "#interface/IApi"; import { Req, Res } from "#interface/IApi";
import queryModifier from "#middlewares/request";
export default (_express: Application) => { export default (_express: Application) => {
const enrollProvider = new EnrollProvider(); const enrollProvider = new EnrollProvider();
...@@ -11,7 +12,7 @@ export default (_express: Application) => { ...@@ -11,7 +12,7 @@ export default (_express: Application) => {
* @openapi * @openapi
* /api/v1.0/enrollments/all-student-in-class: * /api/v1.0/enrollments/all-student-in-class:
* post: * post:
* tags: [enrollments] * tags: [Enrollments]
* description: Xem tất cả học sinh có trong lớp học * description: Xem tất cả học sinh có trong lớp học
* requestBody: * requestBody:
* required: true * required: true
...@@ -30,6 +31,8 @@ export default (_express: Application) => { ...@@ -30,6 +31,8 @@ export default (_express: Application) => {
* $ref: "#/components/schemas/AllStudentInClassOutput" * $ref: "#/components/schemas/AllStudentInClassOutput"
*/ */
post: { post: {
middleware: [queryModifier],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
try { try {
const students = await enrollProvider.getAllStudentInClass(req.body.class_id); const students = await enrollProvider.getAllStudentInClass(req.body.class_id);
......
...@@ -4,6 +4,7 @@ import { EnrollProvider } from "#providers/EnrollProvider.js"; ...@@ -4,6 +4,7 @@ import { EnrollProvider } from "#providers/EnrollProvider.js";
import { authorize } from "#middlewares/authorization"; import { authorize } from "#middlewares/authorization";
import { authMiddleware } from "#middlewares/authentication"; import { authMiddleware } from "#middlewares/authentication";
import { Req, Res } from "#interface/IApi"; import { Req, Res } from "#interface/IApi";
import queryModifier from "#middlewares/request";
export default (_express: Application) => { export default (_express: Application) => {
const enrollProvider = new EnrollProvider(); const enrollProvider = new EnrollProvider();
...@@ -13,7 +14,7 @@ export default (_express: Application) => { ...@@ -13,7 +14,7 @@ export default (_express: Application) => {
* @openapi * @openapi
* /api/v1.0/enrollments/enroll: * /api/v1.0/enrollments/enroll:
* post: * post:
* tags: [enrollments] * tags: [Enrollments]
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* description: Tham gia khoá học * description: Tham gia khoá học
...@@ -29,12 +30,10 @@ export default (_express: Application) => { ...@@ -29,12 +30,10 @@ export default (_express: Application) => {
* content: * content:
* application/json: * application/json:
* schema: * schema:
* type: array
* items:
* $ref: "#/components/schemas/Enrollment" * $ref: "#/components/schemas/Enrollment"
*/ */
post: { post: {
middleware: [authMiddleware, authorize("student")], middleware: [queryModifier, authMiddleware, authorize("student")],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
try { try {
......
...@@ -3,6 +3,7 @@ import type { Resource } from "express-automatic-routes"; ...@@ -3,6 +3,7 @@ import type { Resource } from "express-automatic-routes";
import { EnrollProvider } from "#providers/EnrollProvider.js"; import { EnrollProvider } from "#providers/EnrollProvider.js";
import { authorize } from "#middlewares/authorization"; import { authorize } from "#middlewares/authorization";
import { Req, Res } from "#interface/IApi"; import { Req, Res } from "#interface/IApi";
import queryModifier from "#middlewares/request";
export default (_express: Application) => { export default (_express: Application) => {
const enrollProvider = new EnrollProvider(); const enrollProvider = new EnrollProvider();
...@@ -12,7 +13,7 @@ export default (_express: Application) => { ...@@ -12,7 +13,7 @@ export default (_express: Application) => {
* @openapi * @openapi
* /api/v1.0/enrollments/unenroll: * /api/v1.0/enrollments/unenroll:
* post: * post:
* tags: [enrollments] * tags: [Enrollments]
* description: Hủy đăng ký khóa học * description: Hủy đăng ký khóa học
* requestBody: * requestBody:
* required: true * required: true
...@@ -26,11 +27,10 @@ export default (_express: Application) => { ...@@ -26,11 +27,10 @@ export default (_express: Application) => {
* content: * content:
* application/json: * application/json:
* schema: * schema:
* type: array
* items:
* $ref: "#/components/schemas/Unenrollment" * $ref: "#/components/schemas/Unenrollment"
*/ */
post: { post: {
middleware: [queryModifier],
handler: async (req: Req, res: Res) => { handler: async (req: Req, res: Res) => {
try { try {
const enroll = await enrollProvider.unEnroll(req.body.userId, req.body.classId); const enroll = await enrollProvider.unEnroll(req.body.userId, req.body.classId);
......
import { Req, Res } from "#interface/IApi";
import { RolesProvider } from "#providers/RolesProvider.js";
import { Application } from "express";
import { Resource } from "express-automatic-routes";
import queryModifier from "#middlewares/request";
export default (_express: Application) => {
const rolesProvider = new RolesProvider();
return <Resource>{
/**
* @openapi
* /api/v1.0/roles:
* get:
* tags: [Roles]
* parameters:
* - $ref: '#/components/parameters/filters'
* - $ref: '#/components/parameters/sort'
* - $ref: '#/components/parameters/page'
* - $ref: '#/components/parameters/pageSize'
* responses:
* 200:
* description: Trả về danh sách vai trò thành công
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/RoleListResponse"
*/
get: {
middleware: [queryModifier],
handler: async (req: Req, res: Res) => {
try {
const roles = await rolesProvider.getRoles(req.payload);
res.sendOk({
data: roles,
message: "Lấy danh sách vai trò thành công",
message_en: "Roles fetched successfully",
status: 200
});
} catch (error) {
console.error("Error fetching roles:", error);
res.sendError({
message: "Lấy danh sách vai trò thất bại",
message_en: "Failed to fetch roles",
status: 500
});
}
}
}
};
};
\ No newline at end of file
import { Req, Res } from "#interface/IApi";
import { RolesProvider } from "#providers/RolesProvider.js";
import { Application } from "express";
import { Resource } from "express-automatic-routes";
import { authorize } from "#middlewares/authorization";
import { authMiddleware } from "#middlewares/authentication";
export default (_express: Application) => {
const rolesProvider = new RolesProvider();
return <Resource>{
/**
* @openapi
* /api/v1.0/roles/set-role:
* post:
* tags: [Roles]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/setRoleRequest"
* responses:
* 201:
* description: Cập nhật vai trò thành công
* content:
* application/json:
* schema:
* $ref: "#/components/schemas/SetRoleResponse"
*/
post: {
middleware: [authMiddleware, authorize("admin")],
handler: async (req: Req, res: Res) => {
try {
const setRole = await rolesProvider.setRole(req.body);
res.sendOk({
data: setRole,
message: "Cập nhật vai trò thành công",
message_en: "Role updated successfully",
status: 201
});
} catch (error) {
console.error("Error updating role:", error);
res.sendError({
message: "Cập nhật vai trò thất bại",
message_en: "Failed to update role",
status: 500
});
}
}
}
};
};
\ No newline at end of file
This diff is collapsed.
...@@ -17,21 +17,28 @@ export default function queryModifier(req: Req, _res: Res, next: NextFunction) { ...@@ -17,21 +17,28 @@ export default function queryModifier(req: Req, _res: Res, next: NextFunction) {
const arrFilters = filters.split(","); const arrFilters = filters.split(",");
arrFilters.forEach((element) => { arrFilters.forEach((element) => {
// Mỗi phần tử sẽ có dạng: "status|=|published" hoặc "title|like|NodeJS" // Mỗi phần tử sẽ có dạng: "status == published" hoặc "title @= NodeJS"
const parts = element.split("|"); const trimmedElement = element.trim();
const parts = trimmedElement.match(/^(\S+)\s*(==|@=|>=|<=|>|<)\s*(.+)$/i);
// Phải đủ 3 thành phần: [Tên cột, Toán tử, Giá trị] // Phải đủ 3 thành phần: [Tên cột, Toán tử, Giá trị]
if (parts.length === 3) { if (parts) {
const [field, operator, value] = parts as [string, string, string]; const field = parts[1]?.trim();
const operator = parts[2]?.trim().toLowerCase();
const value = parts[3]?.trim();
if (!field || !operator || value === undefined) {
return;
}
let condition: any = {}; let condition: any = {};
// Dịch toán tử từ URL sang toán tử Sequelize tương ứng // Dịch toán tử từ URL sang toán tử Sequelize tương ứng
switch (operator.toLowerCase()) { switch (operator) {
case "=": case "==":
condition[field] = { [Op.eq]: value }; condition[field] = { [Op.eq]: value };
break; break;
case "like": case "@=":
condition[field] = { [Op.iLike]: `%${value}%` }; condition[field] = { [Op.iLike]: `%${value}%` };
break; break;
case ">": case ">":
......
...@@ -13,7 +13,8 @@ export class CoursesProvider { ...@@ -13,7 +13,8 @@ export class CoursesProvider {
where: params.filters, where: params.filters,
order: params.sortBy ? [[params.sortBy, params.sortOrder]] : [['created_at', 'DESC']], order: params.sortBy ? [[params.sortBy, params.sortOrder]] : [['created_at', 'DESC']],
limit: params.pageSize, limit: params.pageSize,
offset: (params.page - 1) * params.pageSize offset: (params.page - 1) * params.pageSize,
raw: true,
}); });
return { return {
count, count,
......
import { payload } from "#interface/IApi";
import { models } from "#models/sequelize-config.js";
export class RolesProvider {
async getRoles(params: payload) {
const { count, rows } = await models.roles.findAndCountAll({
where: params.filters,
order: params.sortBy ? [[params.sortBy, params.sortOrder]] : [['created_at', 'DESC']],
limit: params.pageSize,
offset: (params.page - 1) * params.pageSize,
raw: true
});
return {
count,
page: params.page,
pageSize: params.pageSize,
rows
};
}
async setRole(body: { user_id: string; role_id: string }) {
const [affectedRows, updatedUsers] = await models.users.update(
{ role_id: body.role_id },
{
where: {
id: body.user_id
},
returning: true,
},
);
return updatedUsers[0];
}
}
...@@ -10,6 +10,7 @@ import sendOTPSchemas from './sendOTP/schema.js'; ...@@ -10,6 +10,7 @@ import sendOTPSchemas from './sendOTP/schema.js';
import verifyOTPSchemas from './verifyOTP/schema.js'; import verifyOTPSchemas from './verifyOTP/schema.js';
import logoutSchemas from './logout/schema.js'; import logoutSchemas from './logout/schema.js';
import enrollmentSchemas from './enrollment/schema.js'; import enrollmentSchemas from './enrollment/schema.js';
import rolesSchemas from './roles/schema.js';
const swaggerOptions: Options = { const swaggerOptions: Options = {
definition: { definition: {
...@@ -36,6 +37,7 @@ const swaggerOptions: Options = { ...@@ -36,6 +37,7 @@ const swaggerOptions: Options = {
...verifyOTPSchemas, ...verifyOTPSchemas,
...logoutSchemas, ...logoutSchemas,
...enrollmentSchemas, ...enrollmentSchemas,
...rolesSchemas,
}, },
parameters: { parameters: {
filters: { filters: {
......
...@@ -10,12 +10,31 @@ const courseSchemas = { ...@@ -10,12 +10,31 @@ const courseSchemas = {
created_by: '2b4f6f8e-19f6-4c5d-93c2-4d7a7c3d1e11', created_by: '2b4f6f8e-19f6-4c5d-93c2-4d7a7c3d1e11',
}, },
properties: { properties: {
id: { type: 'string', format: 'uuid' }, id: {
name: { type: 'string' }, type: 'string',
description: { type: 'string', nullable: true }, format: 'uuid'
status: { type: 'string', nullable: true }, },
created_at: { type: 'string', format: 'date-time', nullable: true }, name: {
created_by: { type: 'string', format: 'uuid', nullable: true }, type: 'string'
},
description: {
type: 'string',
nullable: true
},
status: {
type: 'string',
nullable: true
},
created_at: {
type: 'string',
format: 'date-time',
nullable: true
},
created_by: {
type: 'string',
format: 'uuid',
nullable: true
},
}, },
}, },
CourseResponse: { CourseResponse: {
...@@ -40,23 +59,7 @@ const courseSchemas = { ...@@ -40,23 +59,7 @@ const courseSchemas = {
type: 'string', type: 'string',
example: '2024-02-26 03:12:45', example: '2024-02-26 03:12:45',
}, },
violations: { violations: {},
type: 'array',
items: {
type: 'object',
properties: {
code: {
type: 'number',
},
message: {
type: 'string',
},
action: {
nullable: true,
},
},
},
},
}, },
}, },
......
const enrollmentSchemas = { const enrollmentSchemas = {
EnrollmentInput: { EnrollmentInput: {
type: 'object', type: 'object',
required: ['class_id'],
example: { example: {
class_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', class_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
}, },
properties: { properties: {
class_id: { class_id: {
type: 'string', type: 'string',
format: 'uuid',
example: '3fa85f64-5717-4562-b3fc-2c963f66afa6', example: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
}, },
}, },
...@@ -14,6 +16,7 @@ const enrollmentSchemas = { ...@@ -14,6 +16,7 @@ const enrollmentSchemas = {
UnenrollmentInput: { UnenrollmentInput: {
type: 'object', type: 'object',
required: ['userId', 'classId'],
example: { example: {
userId: '3fa85f64-5717-4562-b3fc-2c963f66afa6', userId: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
classId: '3fa85f64-5717-4562-b3fc-2c963f66afa6', classId: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
...@@ -21,10 +24,12 @@ const enrollmentSchemas = { ...@@ -21,10 +24,12 @@ const enrollmentSchemas = {
properties: { properties: {
userId: { userId: {
type: 'string', type: 'string',
format: 'uuid',
example: '3fa85f64-5717-4562-b3fc-2c963f66afa6', example: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
}, },
classId: { classId: {
type: 'string', type: 'string',
format: 'uuid',
example: '3fa85f64-5717-4562-b3fc-2c963f66afa6', example: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
}, },
}, },
...@@ -35,24 +40,45 @@ const enrollmentSchemas = { ...@@ -35,24 +40,45 @@ const enrollmentSchemas = {
example: { example: {
message: 'Hủy đăng ký khóa học thành công', message: 'Hủy đăng ký khóa học thành công',
}, },
properties: {
message: {
type: 'string',
example: 'Hủy đăng ký khóa học thành công',
},
},
}, },
Enrollment: { Enrollment: {
type: 'object', type: 'object',
example: { example: {
id: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
user_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', user_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
class_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', class_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
created_at: '2026-05-20T00:00:00.000Z',
status: 'active', status: 'active',
}, },
properties: { properties: {
id: {
type: 'string',
format: 'uuid',
example: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
},
user_id: { user_id: {
type: 'string', type: 'string',
format: 'uuid',
example: '3fa85f64-5717-4562-b3fc-2c963f66afa6', example: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
}, },
class_id: { class_id: {
type: 'string', type: 'string',
format: 'uuid',
example: '3fa85f64-5717-4562-b3fc-2c963f66afa6', example: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
}, },
created_at: {
type: 'string',
format: 'date-time',
nullable: true,
example: '2026-05-20T00:00:00.000Z',
},
status: { status: {
type: 'string', type: 'string',
example: 'active', example: 'active',
...@@ -62,12 +88,14 @@ const enrollmentSchemas = { ...@@ -62,12 +88,14 @@ const enrollmentSchemas = {
AllStudentInClassInput: { AllStudentInClassInput: {
type: 'object', type: 'object',
required: ['class_id'],
example: { example: {
class_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6', class_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
}, },
properties: { properties: {
class_id: { class_id: {
type: 'string', type: 'string',
format: 'uuid',
example: '3fa85f64-5717-4562-b3fc-2c963f66afa6', example: '3fa85f64-5717-4562-b3fc-2c963f66afa6',
}, },
}, },
......
const rolesSchemas = {
RoleListResponse: {
type: "object",
properties: {
count: {
type: "integer"
},
page: {
type: "integer"
},
pageSize: {
type: "integer"
},
rows: {
type: "array",
items: {
$ref: "#/components/schemas/Role"
}
}
}
},
Role: {
type: "object",
properties: {
id: {
type: "string"
},
name: {
type: "string"
},
description: {
type: "string"
},
created_at: {
type: "string",
format: "date-time"
},
created_by: {
type: "string"
}
}
},
setRoleRequest: {
type: "object",
properties: {
user_id: {
type: "string"
},
role_id: {
type: "string"
}
},
required: ["user_id", "role_id"]
},
SetRoleResponse: {
type: "object",
properties: {
message: {
type: "string",
example: "Cập nhật vai trò thành công"
},
message_en: {
type: "string",
example: "Role updated successfully"
},
responseData: {
type: "object",
properties: {
id: {
type: "string",
example: "123e4567-e89b-12d3-a456-426614174000"
},
name: {
type: "string",
example: "John Doe"
},
date_of_birth: {
type: "string",
format: "date-time",
example: "1990-09-30T17:00:00.000Z"
},
phone: {
type: "string",
example: "0901234567"
},
email: {
type: "string",
format: "email",
example: "john.doe@example.com"
},
address: {
type: "string",
example: "123 Main St, City, Country"
},
created_at: {
type: "string",
format: "date-time",
example: "2023-01-01T00:00:00.000Z"
},
role_id: {
type: "string",
example: "41d5ac41-3ee4-45cb-a381-a83b07694b99"
}
}
},
status: {
type: "string",
example: "true"
},
timeStamp: {
type: "string",
example: "2026-05-20 13:37:24"
},
violations: {
type: "array",
}
}
}
}
export default rolesSchemas;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment