Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #165

Merged
merged 65 commits into from
Apr 14, 2023
Merged

Dev #165

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
7a35ba6
fix: remove unused validate
nc-minh Feb 27, 2023
dec6c5a
fix: add subject into userExam
nc-minh Feb 27, 2023
649917b
Merge branch 'master' into dev
nc-minh Feb 27, 2023
956f107
feat: create api get all documents by subjectId
nc-minh Feb 28, 2023
41bfadf
fix: remove validation for author field in DocumentDto
nc-minh Feb 28, 2023
a8269b5
fix: update response of verifyAccessToken
nc-minh Feb 28, 2023
9feca53
fix: update response of verifyAccessToken
nc-minh Feb 28, 2023
f4fe5d0
fix: add userInfo into response refreshToken
nc-minh Feb 28, 2023
f65efb3
fix: add subject to response of getDocumentBySubject api
nc-minh Mar 1, 2023
c7b16bf
fix: resolve conflict
nc-minh Mar 1, 2023
d1a4c52
feat: create api get a subject by id
nc-minh Mar 1, 2023
a6e6332
feat: create unique for subject_name
nc-minh Mar 3, 2023
e3ec0c7
fix: return code and message error when create duplicate subject
nc-minh Mar 3, 2023
8006504
feat: update auth api for the admin
nc-minh Mar 10, 2023
b3e9b7f
fix: refreshToken response
nc-minh Mar 13, 2023
c3f329b
feat: [update api approve subject]
nc-minh Mar 14, 2023
4382fb9
fix: resolve conflict
nc-minh Mar 14, 2023
07f71df
fix: error response
nc-minh Mar 14, 2023
895bb07
fix: [TOKEN_EXPIRED response]
nc-minh Mar 14, 2023
7ec732a
fix: [resolve conflict]
nc-minh Mar 14, 2023
2c8973f
feat: [add api update is_approved for admin]
nc-minh Mar 14, 2023
3e901d5
feat: api create new document for admin
nc-minh Mar 15, 2023
4e3c1f5
fix: resolve conflict
nc-minh Mar 15, 2023
34050f5
feat: [Pagination for all of api get all]
nc-minh Mar 16, 2023
86d790f
fix: resolve conflict
nc-minh Mar 16, 2023
4545601
feat: [update metadata(total, currentPage, pageSize) in response]
nc-minh Mar 16, 2023
41dce68
fix: [resolve conflict]
nc-minh Mar 16, 2023
c652694
fix: [resolve conflict]
nc-minh Mar 16, 2023
d0a5fc3
fix: [resolve conflict]
nc-minh Mar 16, 2023
b09dd5a
fix: [resolve conflict]
nc-minh Mar 16, 2023
54f0aa0
feat: [default sort with desc]
nc-minh Mar 16, 2023
bbfa4db
feat/#135 (#136)
locxuandao Mar 18, 2023
a2ee5e1
feat/#138 (#139)
locxuandao Mar 18, 2023
4d0b325
feat: allow users outside the organization
nc-minh Mar 19, 2023
7878433
Merge branch 'master' into dev
nc-minh Mar 19, 2023
6f1f5a3
fix: typo
nc-minh Mar 19, 2023
2e19ed0
Merge branch 'master' into dev
nc-minh Mar 19, 2023
0af57e0
feat: softDelete
nc-minh Mar 19, 2023
ca80a0d
feat: [delete plugin]
nc-minh Mar 20, 2023
61c9be4
feat: [api update document & exam by admin and own]
nc-minh Mar 21, 2023
725f9f9
feat: [Update api documentation and exam by admin and owner]
nc-minh Mar 21, 2023
496380f
fix: resolve conflict
nc-minh Mar 21, 2023
c7cf17f
feat: [...]
nc-minh Mar 22, 2023
818e7de
feat: [:boom:][change the structure, logic, algorithms related to use…
nc-minh Mar 22, 2023
60d8a8e
fix: [:x:][resolve conflict]
nc-minh Mar 22, 2023
ba26cc6
Merge branch 'master' into dev
nc-minh Mar 23, 2023
273b295
feat: [...]
nc-minh Mar 23, 2023
2a57789
feat: [test workflows]
nc-minh Mar 23, 2023
2c52cbf
feat: [test workflows]
nc-minh Mar 23, 2023
e47865a
feat: [test workflows]
nc-minh Mar 23, 2023
3731630
feat: [:zap:][add is_show_info & nickname to user and handle hide use…
nc-minh Mar 24, 2023
a1170ff
fix: [convert pageSize & currentPage from string to number in pipeline]
nc-minh Mar 24, 2023
4cb5e69
fix: [change Dockfile]
nc-minh Mar 24, 2023
bb6b28e
fix: [resolve conflict]
nc-minh Mar 24, 2023
4f61a3c
fix: [author array to object in response]
nc-minh Mar 24, 2023
9408ed6
feat: [...]
nc-minh Mar 24, 2023
64499ef
feat/#146 (#151)
DungNguyen2003 Mar 27, 2023
306c3c2
feat: [add questions into response of draft exam]
nc-minh Mar 27, 2023
dfce741
fix: return wrong hideUserInfoIfRequired
nc-minh Mar 27, 2023
32c8d7b
fix: [resolve conflict]
nc-minh Mar 27, 2023
4e1daec
fix: missing hideUserInfoIfRequired() in GetAllDocumentByAdmin()
nc-minh Mar 27, 2023
7a44d00
feat/#155 (#156)
locxuandao Mar 27, 2023
ae35ee7
fix: resolve conflict
nc-minh Mar 30, 2023
9cbe07f
feat/#160 (#161)
locxuandao Apr 6, 2023
e41f4d1
Feat/#162 (#163)
locxuandao Apr 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/apis/v1/documents/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,9 @@ export const getDocumentsBySubjectId = async (req: RequestWithUser, res: Respons
const result = await service.getDocumentsBySubjectId(input.id);
res.send(fmt.formatResponse(result, Date.now() - req.startTime, 'OK'));
};

export const getDocumentsByOwner = async (req: RequestWithUser, res: Response) => {
const author: ObjectId = req?.user?._id;
const result = await service.getDocumentsByOwner(author);
res.send(fmt.formatResponse(result, Date.now() - req.startTime, 'OK'));
};
3 changes: 3 additions & 0 deletions src/apis/v1/documents/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const router = Router();

router.get('/', authMiddleware, asyncRouteHandler(controller.getDocuments));

router.get('/owner', authMiddleware, asyncRouteHandler(controller.getDocumentsByOwner));

router.post(
'/',
authMiddleware,
Expand Down Expand Up @@ -46,4 +48,5 @@ router.get(
validationMiddleware(ParamsDocumentDto, APP_CONSTANTS.params),
asyncRouteHandler(controller.getDocumentsBySubjectId)
);

export default router;
26 changes: 23 additions & 3 deletions src/apis/v1/documents/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { SubjectModel } from 'models';
import URLParams from 'utils/rest/urlparams';
import { DEFAULT_PAGING } from 'utils/constants';
import { hideUserInfoIfRequired } from 'utils';
import DocumentType from 'models/types/Document';

export const getDocuments = async (urlParams: URLParams) => {
try {
Expand Down Expand Up @@ -152,11 +153,13 @@ export const getDocumentsByAdmin = async (filter: DocumentFilter, urlParams: URL

logger.info(`Get all documents successfully`);

const resultAll = await Promise.all([count, results]);
const resolveAll = await Promise.all([count, results]);
return {
result: resultAll[1],
result: resolveAll[1].map((document: DocumentType) => {
return { ...document.toObject(), author: hideUserInfoIfRequired(document?.author) };
}),
meta: {
total: resultAll[0],
total: resolveAll[0],
currentPage,
pageSize,
},
Expand Down Expand Up @@ -190,6 +193,23 @@ export const getDocumentsBySubjectId = async (subjectId: string) => {
}
};

export const getDocumentsByOwner = async (authorId: ObjectId) => {
try {
const results = await DocumentModel.find({ author: authorId })
.populate('author', '-is_blocked -roles -created_at -updated_at -__v')
.populate('subject', '-is_deleted -created_at -updated_at -__v');

return {
documents: results.map((document) => {
return { ...document.toObject(), author: hideUserInfoIfRequired(document?.author) };
}),
};
} catch (error) {
logger.error(`Error while get documents by Owner: ${error}`);
throw new HttpException(400, ErrorCodes.BAD_REQUEST.MESSAGE, ErrorCodes.BAD_REQUEST.CODE);
}
};

export const updateDocumentByAdmin = async (input: UpdateDocumentByAdminDto, documentId: string) => {
try {
const document = await DocumentModel.findByIdAndUpdate(
Expand Down
8 changes: 7 additions & 1 deletion src/apis/v1/exam/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export const getExamsBySubjectId = async (req: RequestWithUser, res: Response) =
const urlParams: URLParams = req.searchParams;
const input: ParamsExamDto = req.params;
const { result, meta } = await service.getExamsBySubjectId(input.id, urlParams);

res.send(fmt.formatResponse(result, Date.now() - req.startTime, 'OK', meta.total, meta.currentPage, meta.pageSize));
};

Expand Down Expand Up @@ -60,3 +59,10 @@ export const getDraftExam = async (req: RequestWithUser, res: Response) => {

res.send(fmt.formatResponse(result, Date.now() - req.startTime, 'OK'));
};

export const getExamsByOwner = async (req: RequestWithUser, res: Response) => {
const author = req?.user?._id;
const result = await service.getExamsByOwner(String(author));

res.send(fmt.formatResponse(result, Date.now() - req.startTime, 'OK'));
};
2 changes: 2 additions & 0 deletions src/apis/v1/exam/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ router.get('/', authMiddleware, asyncRouteHandler(controller.getExams));

router.get('/draft-exam', authMiddleware, asyncRouteHandler(controller.getDraftExam));

router.get('/owner', authMiddleware, asyncRouteHandler(controller.getExamsByOwner));

router.get(
'/:id',
authMiddleware,
Expand Down
84 changes: 75 additions & 9 deletions src/apis/v1/exam/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { ObjectId } from 'mongodb';
import { ObjectId as ObjectIdType, PipelineStage } from 'mongoose';
import { ErrorCodes, HttpException } from 'exceptions';
import { ExamModel } from 'models';
import { ExamModel, SubjectModel } from 'models';
import { DEFAULT_PAGING } from 'utils/constants';
import { logger } from 'utils/logger';
import URLParams from 'utils/rest/urlparams';
Expand Down Expand Up @@ -70,7 +70,6 @@ export const getExams = async (urlParams: URLParams) => {
$limit: Number(pageSize),
},
]);

const resolveAll = await Promise.all([count, data]);
return {
result: resolveAll[1].map((exam: Exam) => {
Expand Down Expand Up @@ -131,6 +130,7 @@ export const getExamById = async (id: string) => {
_id: 1,
title: 1,
description: 1,
is_approved: 1,
author: {
_id: '$author._id',
fullname: '$author.fullname',
Expand Down Expand Up @@ -181,7 +181,7 @@ export const getExamsBySubjectId = async (subjectId: string, urlParams: URLParam
const count = ExamModel.countDocuments({ subject: subjectId });
const data = ExamModel.aggregate([
{
$match: { subject: _id },
$match: { subject: _id, is_approved: true },
},
{
$lookup: {
Expand Down Expand Up @@ -233,13 +233,17 @@ export const getExamsBySubjectId = async (subjectId: string, urlParams: URLParam
$limit: Number(pageSize),
},
]);

const resolveAll = await Promise.all([count, data]);
const subject = SubjectModel.findOne({ _id: subjectId });
const resolveAll = await Promise.all([count, data, subject]);

return {
result: resolveAll[1].map((exam: Exam) => {
return { ...exam, author: hideUserInfoIfRequired(exam?.author) };
}),
result: {
exams: resolveAll[1].map((exam: Exam) => {
return { ...exam, author: hideUserInfoIfRequired(exam?.author) };
}),
subject: resolveAll[2],
},

meta: {
total: resolveAll[0],
pageSize,
Expand All @@ -251,7 +255,69 @@ export const getExamsBySubjectId = async (subjectId: string, urlParams: URLParam
throw new HttpException(400, ErrorCodes.BAD_REQUEST.MESSAGE, ErrorCodes.BAD_REQUEST.CODE);
}
};

export const getExamsByOwner = async (authorId: string) => {
try {
const _id = new ObjectId(authorId);
const count = ExamModel.countDocuments({ author: authorId });
const data = ExamModel.aggregate([
{
$match: { author: _id },
},
{
$lookup: {
from: 'question',
localField: '_id',
foreignField: 'exam_id',
as: 'questions',
},
},
{
$lookup: {
from: 'user',
localField: 'author',
foreignField: '_id',
as: 'author',
},
},
{
$lookup: {
from: 'subject',
localField: 'subject',
foreignField: '_id',
as: 'subject',
},
},
{
$unwind: '$subject',
},
{
$unwind: '$author',
},
{
$project: {
'author.is_blocked': 0,
'author.roles': 0,
'author.created_at': 0,
'author.updated_at': 0,
'author.__v': 0,
'questions.author': 0,
},
},
{
$sort: { created_at: -1 },
},
]);
const resolveAll = await Promise.all([count, data]);
return {
exams: resolveAll[1].map((exam: Exam) => {
return { ...exam, author: hideUserInfoIfRequired(exam?.author) };
}),
};
} catch (error) {
logger.error(`Error while get exam by Owner: ${error}`);
throw new HttpException(400, ErrorCodes.BAD_REQUEST.MESSAGE, ErrorCodes.BAD_REQUEST.CODE);
}
};
export const createExam = async (input: ExamDto, author: ObjectIdType) => {
try {
const exam = {
Expand Down
7 changes: 7 additions & 0 deletions src/apis/v1/questions/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,10 @@ export const deleteQuestion = async (req: RequestWithUser, res: Response) => {
const result = await service.deleteQuestion(params.id);
res.send(fmt.formatResponse(result, Date.now() - req.startTime, 'OK'));
};

export const getQuestionsByExamId = async (req: RequestWithUser, res: Response) => {
const params: ParamsQuestionDto = req.params;

const result = await service.getQuestionsByExamId(params.id);
res.send(fmt.formatResponse(result, Date.now() - req.startTime, 'OK'));
};
6 changes: 6 additions & 0 deletions src/apis/v1/questions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ import { QuestionDto, UpdateQuestionDto, ParamsQuestionDto } from './dto/Questio
const router = Router();

router.get('/', authMiddleware, asyncRouteHandler(controller.getQuestions));
router.get(
'/exam/:id',
authMiddleware,
validationMiddleware(ParamsQuestionDto, APP_CONSTANTS.params),
asyncRouteHandler(controller.getQuestionsByExamId)
);

router.post(
'/',
Expand Down
24 changes: 24 additions & 0 deletions src/apis/v1/questions/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import QuestionModel from 'models/schema/Question';
import { DEFAULT_PAGING } from 'utils/constants';
import { logger } from 'utils/logger';
import URLParams from 'utils/rest/urlparams';
import { hideUserInfoIfRequired } from 'utils';

import { QuestionDto, UpdateQuestionDto } from './dto/QuestionDto';
import { ExamModel } from 'models';

export const createQuestion = async function (input: QuestionDto, author: ObjectId) {
try {
Expand Down Expand Up @@ -96,3 +98,25 @@ export const deleteQuestion = async function (id: string) {
throw new HttpException(400, ErrorCodes.BAD_REQUEST.MESSAGE, ErrorCodes.BAD_REQUEST.CODE);
}
};

export const getQuestionsByExamId = async function (examId: string) {
try {
const data = await QuestionModel.find({ exam_id: examId });

const exam = ExamModel.findOne({ _id: examId })
.populate('subject', '-is_deleted -created_at -updated_at -__v')
.populate('author', '-is_blocked -roles -created_at -updated_at -__v');
const resultAll = await Promise.all([data, exam]);

return {
questions: resultAll[0],
exam: {
...resultAll[1].toObject(),
author: hideUserInfoIfRequired(resultAll[1].author),
},
};
} catch (error) {
logger.error(`Error while get questions by examId: ${error}`);
throw new HttpException(400, ErrorCodes.BAD_REQUEST.MESSAGE, ErrorCodes.BAD_REQUEST.CODE);
}
};
6 changes: 3 additions & 3 deletions src/models/schema/Document.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { model, Model, Schema } from 'mongoose';

import { MODELS } from 'utils/constants/models';
import Documents from 'models/types/Document';
import DocumentType from 'models/types/Document';
import { Content } from 'utils/types';
import { softDeletePlugin } from 'models/SoftDeleteModel';

const DocumentSchema = new Schema<Documents>(
const DocumentSchema = new Schema<DocumentType>(
{
author: { type: Schema.Types.ObjectId, ref: MODELS.user, required: true },
title: { type: String, required: true },
Expand All @@ -26,5 +26,5 @@ DocumentSchema.plugin(softDeletePlugin);

DocumentSchema.index({ title: 1, description: 1 });

const DocumentModel: Model<Document> = model<Document>(MODELS.document, DocumentSchema, MODELS.document);
const DocumentModel: Model<DocumentType> = model<DocumentType>(MODELS.document, DocumentSchema, MODELS.document);
export default DocumentModel;
2 changes: 1 addition & 1 deletion src/models/types/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Content } from 'utils/types';
import Subject from './Subject';
import User from './User';

export default interface Documents extends Document {
export default interface DocumentType extends Document {
author: User;
title: string;
description: string;
Expand Down
2 changes: 1 addition & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const hideUserInfoIfRequired = (user: User) => {
}

return {
_id: user._id,
_id: user?._id,
nickname: user?.nickname,
};
};