diff --git a/db.ts b/db.ts index 7f5eea5..ab2b6f5 100644 --- a/db.ts +++ b/db.ts @@ -15,10 +15,10 @@ const makeConnectionWithDB = async () => { try { await sequelize.authenticate(); // if (process.env.NODE_ENV === "development") { - await sequelize.sync({ - force: true, - logging: (sql) => console.log(sql), - }); + // await sequelize.sync({ + // force: true, + // logging: (sql) => console.log(sql), + // }); // } console.log("Connection has been established successfully."); } catch (error) { diff --git a/index.ts b/index.ts index 2cea331..e35d0de 100644 --- a/index.ts +++ b/index.ts @@ -34,7 +34,7 @@ async function makeDatabase() { await makeConnectionWithDB(); } -app.use(express.json({ limit: "1kb" })); +app.use(express.json({ limit: "5kb" })); routes(app); diff --git a/routes.ts b/routes.ts index 6a412ec..eccb711 100644 --- a/routes.ts +++ b/routes.ts @@ -15,11 +15,11 @@ function routes(app: Express): void { app.use(verifyJWT); - // app.use("/api/v2/subject", subjectRouter); + app.use("/api/v2/subject", subjectRouter); - // app.use("/api/v2/topic", topicRouter); + app.use("/api/v2/topic", topicRouter); - // app.use("/api/v2/question", questionRouter); + app.use("/api/v2/question", questionRouter); app.use(verifyPermission); diff --git a/src/DataAccessLayer/question.dal.ts b/src/DataAccessLayer/question.dal.ts index 6ada827..94e88ab 100644 --- a/src/DataAccessLayer/question.dal.ts +++ b/src/DataAccessLayer/question.dal.ts @@ -7,47 +7,43 @@ export const createQuestionDal = async ( }; export const updateQuestionDal = async ( - questionName: string, + questionId: number, payload: Partial ): Promise => { - const question = await Question.findOne({ - where: { question_name: questionName }, - }); + const question = await Question.findByPk(questionId); if (!question) throw "Question not found"; const updatedQuestion = question.set({ - question_description: payload.question_description, + description: payload.description, difficulty: payload.difficulty, - leet_code_problem_link: payload.leet_code_problem_link, - question_name: payload.question_name, - youtube_video_link: payload.youtube_video_link, - under_which_topic: payload.under_which_topic, + problemLink: payload.problemLink, + name: payload.name, + videoLink: payload.videoLink, + underWhichTopic: payload.underWhichTopic, }); await updatedQuestion.save(); return updatedQuestion; }; export const getQuestionsUnderTopicDal = async ( - topicName: string + topicId: number ): Promise => { const questions = await Question.findAll({ - where: { under_which_topic: topicName }, + where: { underWhichTopic: topicId }, limit: 20, }); - if (questions.length === 0) throw `questions not found for ${topicName}`; + if (questions.length === 0) throw `questions not found for ${topicId}`; return questions; }; -export const getQuestionByNameDal = async ( - questionName: string +export const getQuestionByIdDal = async ( + questionId: number ): Promise => { - const question = await Question.findOne({ - where: { question_name: questionName }, - }); + const question = await Question.findByPk(questionId); if (!question) throw "Question not found"; return question; }; -export const deleteQuestionByNameDal = async (questionName: string) => { - return await Question.destroy({ where: { question_name: questionName } }); +export const deleteQuestionByIdDal = async (questionId: number) => { + return await Question.destroy({ where: { id: questionId } }); }; diff --git a/src/DataAccessLayer/subject.dal.ts b/src/DataAccessLayer/subject.dal.ts index 1a61323..d485432 100644 --- a/src/DataAccessLayer/subject.dal.ts +++ b/src/DataAccessLayer/subject.dal.ts @@ -7,19 +7,19 @@ export const createSubjectDal = async ( }; export const updateSubjectDal = async ( - subjectName: string, + subjectId: string, payload: Partial ): Promise => { const subject = await Subject.findOne({ - where: { subject_name: subjectName }, + where: { id: subjectId }, }); if (!subject) throw "Subject not found"; const updatedSubject = subject.set({ - subject_description: payload.subject_description, - image_url: payload.image_url, - subject_name: payload.subject_name, - topic_count: payload.topic_count, + description: payload.description, + imageUrl: payload.imageUrl, + name: payload.name, + topicCount: payload.topicCount, }); await updatedSubject.save(); return updatedSubject; @@ -29,16 +29,14 @@ export const getAllSubjectsDal = async (): Promise => { return await Subject.findAll({ limit: 20 }); }; -export const getSubjectByNameDal = async ( - subjectName: string +export const getSubjectByIdDal = async ( + subjectId: number ): Promise => { - const subject = await Subject.findOne({ - where: { subject_name: subjectName }, - }); + const subject = await Subject.findByPk(subjectId); if (!subject) throw "Subject not found"; return subject; }; -export const deleteSubjectByNameDal = async (name: string) => { - return await Subject.destroy({ where: { subject_name: name } }); +export const deleteSubjectByIdDal = async (subjectId: string) => { + return await Subject.destroy({ where: { id: subjectId } }); }; diff --git a/src/DataAccessLayer/topicUnderSubject.dal.ts b/src/DataAccessLayer/topicUnderSubject.dal.ts index 3ea7b7f..84b28c5 100644 --- a/src/DataAccessLayer/topicUnderSubject.dal.ts +++ b/src/DataAccessLayer/topicUnderSubject.dal.ts @@ -11,45 +11,45 @@ export const createTopicUnderSubjectDal = async ( }; export const updateTopicUnderSubjectDal = async ( - topicName: string, + topicId: number, payload: Partial ): Promise => { const topic = await TopicUnderSubject.findOne({ - where: { topic_name: topicName }, + where: { id: topicId }, }); if (!topic) throw "Topic not found"; const updatedTopic = topic.set({ - topic_description: payload.topic_description, - topic_name: payload.topic_name, - question_count: payload.question_count, - under_which_subject: payload.under_which_subject, + description: payload.description, + name: payload.name, + questionCount: payload.questionCount, + underWhichSubject: payload.underWhichSubject, }); await updatedTopic.save(); return updatedTopic; }; export const getAllTopicsUnderSubjectDal = async ( - subjectName: string + subjectId: number ): Promise => { const topics = await TopicUnderSubject.findAll({ - where: { under_which_subject: subjectName }, + where: { underWhichSubject: subjectId }, limit: 20, }); - if (topics.length === 0) throw `no topics found for ${subjectName}`; + if (topics.length === 0) throw `no topics found for ${subjectId}`; return topics; }; export const getTopicByNameDal = async ( - topicName: string + topicId: number ): Promise => { const question = await TopicUnderSubject.findOne({ - where: { topic_name: topicName }, + where: { id: topicId }, }); if (!question) throw "Question not found"; return question; }; -export const deleteTopicByNameDal = async (topicName: string) => { - return await TopicUnderSubject.destroy({ where: { topic_name: topicName } }); +export const deleteTopicByIdDal = async (topicId: number) => { + return await TopicUnderSubject.destroy({ where: { id: topicId } }); }; diff --git a/src/controller/auth.controller.ts b/src/controller/auth.controller.ts index 570674f..4a4fb97 100644 --- a/src/controller/auth.controller.ts +++ b/src/controller/auth.controller.ts @@ -83,7 +83,6 @@ async function updateUser(request: Request, response: Response) { if (!cookies?.jwt) return response.sendStatus(204); try { const refreshToken = cookies.jwt; - if (refreshToken.length !== 187) return response.sendStatus(401); if (!user.verified) { return successResponse(response, 200, { message: "Account is not verified!", @@ -142,7 +141,6 @@ async function logout(request: Request, response: Response) { try { const refreshToken: string = cookies.jwt; - if (refreshToken.length !== 187) return response.sendStatus(401); let user = await getUserByRefreshTokenDal(refreshToken); if (!user) { @@ -161,11 +159,12 @@ async function logout(request: Request, response: Response) { async function handleRefreshToken(request: Request, response: Response) { const cookies = request.cookies; + console.log(cookies); if (!cookies?.jwt) return response.sendStatus(204); try { const refreshToken: string = cookies.jwt; - if (refreshToken.length !== 187) return response.sendStatus(401); + console.log(refreshToken.length); let user = await getUserByRefreshTokenDal(refreshToken); if (!user) return response.sendStatus(403); @@ -189,7 +188,6 @@ async function getUserRefreshToken(request: Request, response: Response) { try { const refreshToken: string = cookies.jwt; - if (refreshToken.length !== 187) return response.sendStatus(401); let user = await getUserByRefreshTokenDal(refreshToken); if (!user) return response.sendStatus(404); diff --git a/src/controller/question.controller.ts b/src/controller/question.controller.ts index d9af316..4412a56 100644 --- a/src/controller/question.controller.ts +++ b/src/controller/question.controller.ts @@ -1,8 +1,8 @@ import { Request, Response } from "express"; import { createQuestionDal, - deleteQuestionByNameDal, - getQuestionByNameDal, + deleteQuestionByIdDal, + getQuestionByIdDal, getQuestionsUnderTopicDal, updateQuestionDal, } from "../DataAccessLayer/question.dal"; @@ -20,9 +20,11 @@ async function createQuestion(request: Request, response: Response) { async function updateQuestion(request: Request, response: Response) { const body = request.body; - const questionName = request.params.questionName; try { - const updatedQuestion = await updateQuestionDal(questionName, body); + const updatedQuestion = await updateQuestionDal( + parseInt(body.questionId as string), + body + ); successResponse(response, 201, updatedQuestion); } catch (error) { return errorResponse(response, 500, error); @@ -30,19 +32,21 @@ async function updateQuestion(request: Request, response: Response) { } async function getQuestionsUnderATopic(request: Request, response: Response) { - const topicName = request.params.topicName; + const topicId = request.query.topicId; try { - const questions = await getQuestionsUnderTopicDal(topicName); + const questions = await getQuestionsUnderTopicDal( + parseInt(topicId as string) + ); successResponse(response, 200, questions); } catch (error) { errorResponse(response, 500, error); } } -async function getQuestionByName(request: Request, response: Response) { - const questionName = request.params.questionName; +async function getQuestionById(request: Request, response: Response) { + const questionId = request.query.questionId; try { - const question = await getQuestionByNameDal(questionName); + const question = await getQuestionByIdDal(parseInt(questionId as string)); successResponse(response, 200, question); } catch (error) { errorResponse(response, 500, error); @@ -50,10 +54,10 @@ async function getQuestionByName(request: Request, response: Response) { } async function deleteQuestion(request: Request, response: Response) { - const questionName = request.params.questionName; + const questionId = request.body.questionId; try { - await deleteQuestionByNameDal(questionName); - successResponse(response, 200, "Deleted successfully"); + await deleteQuestionByIdDal(parseInt(questionId as string)); + successResponse(response, 200, { deleted: questionId }); } catch (error) { errorResponse(response, 500, error); } @@ -62,7 +66,7 @@ async function deleteQuestion(request: Request, response: Response) { export default { createQuestion, deleteQuestion, - getQuestionByName, + getQuestionById, getQuestionsUnderATopic, updateQuestion, }; diff --git a/src/controller/subject.controller.ts b/src/controller/subject.controller.ts index b580f80..e4dfc60 100644 --- a/src/controller/subject.controller.ts +++ b/src/controller/subject.controller.ts @@ -1,9 +1,9 @@ import { Request, Response } from "express"; import { createSubjectDal, - deleteSubjectByNameDal, + deleteSubjectByIdDal, getAllSubjectsDal, - getSubjectByNameDal, + getSubjectByIdDal, updateSubjectDal, } from "../DataAccessLayer/subject.dal"; @@ -15,17 +15,21 @@ async function createSubject(request: Request, response: Response) { const subject = await createSubjectDal(body); return successResponse(response, 201, subject); } catch (error) { + console.log(error); return errorResponse(response, 500, error); } } async function updateSubject(request: Request, response: Response) { - const subjectName = request.params.subjectName; const body = request.body; try { - const subject = await updateSubjectDal(subjectName, body); + const subject = await updateSubjectDal( + body.subjectId as string, + body + ); return successResponse(response, 201, subject); } catch (error: any) { + console.log(error); return errorResponse(response, 500, error); } } @@ -35,14 +39,15 @@ async function getAllSubject(request: Request, response: Response) { const subjects = await getAllSubjectsDal(); return successResponse(response, 200, subjects); } catch (error) { + console.log(error); return errorResponse(response, 500, error); } } -async function getSubjectByName(request: Request, response: Response) { - const subjectName = request.params.subjectName; +async function getSubjectById(request: Request, response: Response) { + const subjectId = request.query.subjectId; try { - const result = await getSubjectByNameDal(subjectName); + const result = await getSubjectByIdDal(parseInt(subjectId as string)); return successResponse(response, 200, result); } catch (error) { errorResponse(response, 500, error); @@ -50,11 +55,12 @@ async function getSubjectByName(request: Request, response: Response) { } async function deleteSubjectByName(request: Request, response: Response) { - const subjectName = request.params.subjectName; + const body = request.body; try { - await deleteSubjectByNameDal(subjectName); - return successResponse(response, 200, "Deleted successfully"); + await deleteSubjectByIdDal(body.subjectId as string); + return successResponse(response, 200, { deleted: body.subjectId }); } catch (error) { + console.log(error); errorResponse(response, 500, error); } } @@ -63,6 +69,6 @@ export default { createSubject, getAllSubject, deleteSubjectByName, - getSubjectByName, + getSubjectById, updateSubject, }; diff --git a/src/controller/topicUnderSubject.controller.ts b/src/controller/topicUnderSubject.controller.ts index d954a94..593bf08 100644 --- a/src/controller/topicUnderSubject.controller.ts +++ b/src/controller/topicUnderSubject.controller.ts @@ -2,7 +2,7 @@ import { Request, Response } from "express"; import { createTopicUnderSubjectDal, - deleteTopicByNameDal, + deleteTopicByIdDal, getAllTopicsUnderSubjectDal, getTopicByNameDal, updateTopicUnderSubjectDal, @@ -21,9 +21,11 @@ async function createTopic(request: Request, response: Response) { async function updateTopic(request: Request, response: Response) { const body = request.body; - const topicName = request.params.topicName; try { - const updatedTopic = await updateTopicUnderSubjectDal(topicName, body); + const updatedTopic = await updateTopicUnderSubjectDal( + parseInt(body.topicId as string), + body + ); successResponse(response, 200, updatedTopic); } catch (error) { return errorResponse(response, 500, error); @@ -31,19 +33,21 @@ async function updateTopic(request: Request, response: Response) { } async function getAllTopicsUnderSubject(request: Request, response: Response) { - const subjectName = request.params.subjectName; + const subjectId = request.query.subjectId; try { - const topics = await getAllTopicsUnderSubjectDal(subjectName); + const topics = await getAllTopicsUnderSubjectDal( + parseInt(subjectId as string) + ); successResponse(response, 200, topics); } catch (error) { errorResponse(response, 500, error); } } -async function getTopicByName(request: Request, response: Response) { - const topicName = request.params.topicName; +async function getTopicById(request: Request, response: Response) { + const topicId = request.query.topicId; try { - const topic = await getTopicByNameDal(topicName); + const topic = await getTopicByNameDal(parseInt(topicId as string)); successResponse(response, 200, topic); } catch (error) { errorResponse(response, 500, error); @@ -51,10 +55,10 @@ async function getTopicByName(request: Request, response: Response) { } async function deleteTopic(request: Request, response: Response) { - const topicName = request.params.topicName; + const body = request.body; try { - await deleteTopicByNameDal(topicName); - successResponse(response, 200, "Deleted successfully"); + await deleteTopicByIdDal(parseInt(body.topicId as string)); + successResponse(response, 200, { deleted: body.topicId }); } catch (error) { errorResponse(response, 500, error); } @@ -63,7 +67,7 @@ async function deleteTopic(request: Request, response: Response) { export default { createTopic, updateTopic, - getTopicByName, + getTopicById, deleteTopic, getAllTopicsUnderSubject, }; diff --git a/src/middleware/verifyAdminPermission.ts b/src/middleware/verifyAdminPermission.ts index 64c4887..478f1c4 100644 --- a/src/middleware/verifyAdminPermission.ts +++ b/src/middleware/verifyAdminPermission.ts @@ -5,7 +5,7 @@ dotenv.config(); type JwtPayload = { role: string; - _id: string; + id: string; }; const verifyAdminPermission = ( @@ -17,7 +17,7 @@ const verifyAdminPermission = ( if (!authHeader) return response.sendStatus(401); const token = authHeader.split(" ")[1]; try { - const { role, _id } = jwt.verify( + const { role, id } = jwt.verify( token, process.env.JWT_SECRET! ) as JwtPayload; diff --git a/src/middleware/verifyUserPermission.ts b/src/middleware/verifyUserPermission.ts index e935c8b..55055f4 100644 --- a/src/middleware/verifyUserPermission.ts +++ b/src/middleware/verifyUserPermission.ts @@ -5,7 +5,7 @@ dotenv.config(); type JwtPayload = { role: string; - _id: string; + id: string; }; const verifyPermission = ( @@ -17,11 +17,11 @@ const verifyPermission = ( if (!authHeader) return response.sendStatus(401); const token = authHeader.split(" ")[1]; try { - const { role, _id } = jwt.verify( + const { role, id } = jwt.verify( token, process.env.JWT_SECRET! ) as JwtPayload; - console.log(role, _id); + console.log(role, id); if (role !== "user") return response.sendStatus(403); next(); } catch (error) { diff --git a/src/models/Question.ts b/src/models/Question.ts index 8e08d10..7d7c178 100644 --- a/src/models/Question.ts +++ b/src/models/Question.ts @@ -38,7 +38,7 @@ Question.init( id: { type: DataTypes.INTEGER, allowNull: false, - defaultValue: DataTypes.INTEGER, + autoIncrement: true, primaryKey: true, unique: true, }, diff --git a/src/models/Subject.ts b/src/models/Subject.ts index e5a0f18..89d9908 100644 --- a/src/models/Subject.ts +++ b/src/models/Subject.ts @@ -30,7 +30,7 @@ Subject.init( id: { type: DataTypes.INTEGER, allowNull: false, - defaultValue: DataTypes.INTEGER, + autoIncrement: true, unique: true, primaryKey: true, }, diff --git a/src/models/TopicUnderSubject.ts b/src/models/TopicUnderSubject.ts index d82bdbb..09dfbae 100644 --- a/src/models/TopicUnderSubject.ts +++ b/src/models/TopicUnderSubject.ts @@ -7,7 +7,7 @@ interface TopicUnderSubjectAttributes { name: string; description: string; questionCount: number; - underWhichSubject: string; + underWhichSubject: number; } export interface TopicUnderSubjectInput @@ -24,7 +24,7 @@ export class TopicUnderSubject public name!: string; public description!: string; public questionCount!: number; - public underWhichSubject!: string; + public underWhichSubject!: number; public readonly createdAt!: Date; public readonly updatedAt!: Date; } diff --git a/src/routes/question.routes.ts b/src/routes/question.routes.ts index de846ff..1164723 100644 --- a/src/routes/question.routes.ts +++ b/src/routes/question.routes.ts @@ -23,7 +23,7 @@ router.post( // update a question by name // localhost:5000/api/v2/question router.put( - "/:questionName", + "/", verifyAdminPermission, validateAsync(updateQuestionSchema), questionController.updateQuestion @@ -32,7 +32,7 @@ router.put( // delete a question by name // localhost:5000/api/v2/question/:questionName router.delete( - "/:questionName", + "/", verifyAdminPermission, validateAsync(deleteQuestionSchema), questionController.deleteQuestion @@ -41,16 +41,16 @@ router.delete( // get a question by name // localhost:5000/api/v2/question/:questionName router.get( - "/:questionName", + "/", verifyAdminPermission, validateAsync(deleteQuestionSchema), - questionController.getQuestionByName + questionController.getQuestionById ); // get all questions under a topic // localhost:5000/api/v2/question/topic/:topic router.get( - "/topic/:topicName", + "/topic", verifyAdminPermission, validateAsync(deleteTopicUnderSubjectSchema), questionController.getQuestionsUnderATopic diff --git a/src/routes/subject.routes.ts b/src/routes/subject.routes.ts index 36edd96..c06a0eb 100644 --- a/src/routes/subject.routes.ts +++ b/src/routes/subject.routes.ts @@ -5,8 +5,9 @@ import { validateAsync } from "../middleware/validateResources"; import verifyAdminPermission from "../middleware/verifyAdminPermission"; import { createSubjectSchema, - deleteSubjectSchema, updateSubjectSchema, + deleteSubjectByIdSchema, + getSubjectByIdSchema, } from "../schema/subject.schema"; const router = express.Router(); @@ -23,7 +24,7 @@ router.post( // update a subject by name // localhost:5000/api/v2/subject/:subjectName router.put( - "/:subjectName", + "/", verifyAdminPermission, validateAsync(updateSubjectSchema), subjectController.updateSubject @@ -32,9 +33,9 @@ router.put( // delete a subject by name // localhost:5000/api/v2/subject/:subjectName router.delete( - "/:subjectName", + "/", verifyAdminPermission, - validateAsync(deleteSubjectSchema), + validateAsync(deleteSubjectByIdSchema), subjectController.deleteSubjectByName ); @@ -45,10 +46,10 @@ router.get("/", verifyAdminPermission, subjectController.getAllSubject); // get one subject by name // localhost:5000/api/v2/subject/:subjectName router.get( - "/:subjectName", + "/", verifyAdminPermission, - validateAsync(deleteSubjectSchema), - subjectController.getSubjectByName + validateAsync(getSubjectByIdSchema), + subjectController.getSubjectById ); export default router; diff --git a/src/routes/topicUnderSubject.routes.ts b/src/routes/topicUnderSubject.routes.ts index 9c12180..ab5793e 100644 --- a/src/routes/topicUnderSubject.routes.ts +++ b/src/routes/topicUnderSubject.routes.ts @@ -3,11 +3,12 @@ import express from "express"; import topicUnderSubject from "../controller/topicUnderSubject.controller"; import { validateAsync } from "../middleware/validateResources"; import verifyAdminPermission from "../middleware/verifyAdminPermission"; -import { deleteSubjectSchema } from "../schema/subject.schema"; +import { deleteSubjectByIdSchema } from "../schema/subject.schema"; import { createTopicUnderSubjectSchema, deleteTopicUnderSubjectSchema, + getTopicByIdSchema, updateTopicUnderSubjectSchema, } from "../schema/topicUnderSubject.schema"; @@ -25,7 +26,7 @@ router.post( // update a topic by name // localhost:5000/api/v2/topic/ router.put( - "/:topicName", + "/", verifyAdminPermission, validateAsync(updateTopicUnderSubjectSchema), topicUnderSubject.updateTopic @@ -34,7 +35,7 @@ router.put( // delete a topic by name // localhost:5000/api/v2/topic/:topicName router.delete( - "/:topicName", + "/", verifyAdminPermission, validateAsync(deleteTopicUnderSubjectSchema), topicUnderSubject.deleteTopic @@ -43,18 +44,18 @@ router.delete( // get a topic by name // localhost:5000/api/v2/topic/:topicName router.get( - "/:topicName", + "/", verifyAdminPermission, - validateAsync(deleteTopicUnderSubjectSchema), - topicUnderSubject.getTopicByName + validateAsync(getTopicByIdSchema), + topicUnderSubject.getTopicById ); // get all topics under a subject // localhost:5000/api/v2/topic/subject/:subjectName router.get( - "/subject/:subjectName", + "/subject", verifyAdminPermission, - validateAsync(deleteSubjectSchema), + validateAsync(deleteSubjectByIdSchema), topicUnderSubject.getAllTopicsUnderSubject ); diff --git a/src/schema/question.schema.ts b/src/schema/question.schema.ts index 221338a..7e7d297 100644 --- a/src/schema/question.schema.ts +++ b/src/schema/question.schema.ts @@ -1,10 +1,10 @@ -import { object, string } from "zod"; +import { number, object, string } from "zod"; import { Question } from "../models/Question"; import { TopicUnderSubject } from "../models/TopicUnderSubject"; export const createQuestionSchema = object({ body: object({ - question_name: string({ + name: string({ required_error: "questionName is required", }) .nonempty({ message: "name can't be empty" }) @@ -14,14 +14,14 @@ export const createQuestionSchema = object({ .refine( async (questionName) => { const question = await Question.findOne({ - where: { question_name: questionName }, + where: { name: questionName }, }); if (question) return false; else return true; }, { message: "question name already exists" } ), - question_description: string({ + description: string({ required_error: "questionDescription is required", }) .nonempty({ message: "description can't be empty" }) @@ -47,15 +47,15 @@ export const createQuestionSchema = object({ message: "Difficulty should be easy,medium,hard only", } ), - youtube_video_link: string({ - required_error: "youtubeVideoLink is required", + videoLink: string({ + required_error: "videoLink is required", }) .url("should be a url") - .nonempty({ message: "youtube link can't be empty" }) + .nonempty({ message: "videoLink can't be empty" }) .trim() .refine( (value) => { - if (value.includes("https://www.youtube.com/watch?v=")) return true; + if (value.includes("https://")) return true; else return false; }, { @@ -65,7 +65,7 @@ export const createQuestionSchema = object({ .refine( async (value) => { const question = await Question.findOne({ - where: { youtube_video_link: value }, + where: { videoLink: value }, }); if (question) return false; else return true; @@ -75,72 +75,50 @@ export const createQuestionSchema = object({ "Question video link exists for the question.The solution will be different for all questions so change link", } ), - leet_code_problem_link: string({ - required_error: "leetCodeProblemLink is required", + problemLink: string({ + required_error: "problemLink is required", }) .url("should be a url") - .nonempty({ message: "leetcode link can't be empty" }) + .nonempty({ message: "problemLink can't be empty" }) .trim() - .refine( - (value) => { - if (value.includes("https://leetcode.com/problems")) return true; - else return false; - }, - { - message: "Invalid leetcode link format", - } - ) + .refine( async (value) => { const question = await Question.findOne({ - where: { leet_code_problem_link: value }, + where: { problemLink: value }, }); if (question) return false; else return true; }, { message: - "Leet code link cannot be duplicate for 2 questions change leetcode link", + "problemLink cannot be duplicate for 2 questions change leetcode link", } ), - under_which_topic: string({ + underWhichTopic: number({ required_error: "under which topic is required", - }) - .trim() - .nonempty({ message: "under which topic link can't be empty" }) - .refine( - async (topicName) => { - const topic = await TopicUnderSubject.findOne({ - where: { topic_name: topicName }, - }); - if (topic) return true; - else return false; - }, - { message: " Entered topic name does not exists" } - ), + }).refine( + async (topicId) => { + const topic = await TopicUnderSubject.findByPk(topicId); + if (topic) return true; + else return false; + }, + { message: " Entered topic name does not exists" } + ), }), }); export const updateQuestionSchema = object({ - params: object({ - questionName: string() - .nonempty({ message: "name can't be empty" }) - .min(5, "question_name should not be less than 5 characters") - .max(30, "question_name should be not be greater than 30 characters") - .trim() - .refine( - async (questionName) => { - const question = await Question.findOne({ - where: { question_name: questionName }, - }); - if (question) return true; - else return false; - }, - { message: "question_name does not exist" } - ), - }), body: object({ - question_name: string({ + questionId: number({ required_error: "questionId is required" }).refine( + async (questionId) => { + const question = await Question.findByPk(questionId); + if (question) return true; + else return false; + }, + { message: "questionId does not exist" } + ), + name: string({ required_error: "questionName is required", }) .nonempty({ message: "name can't be empty" }) @@ -150,14 +128,14 @@ export const updateQuestionSchema = object({ .refine( async (questionName) => { const question = await Question.findOne({ - where: { question_name: questionName }, + where: { name: questionName }, }); if (question) return true; else return false; }, { message: "question name does not exists" } ), - question_description: string({ + description: string({ required_error: "questionDescription is required", }) .nonempty({ message: "description can't be empty" }) @@ -183,71 +161,59 @@ export const updateQuestionSchema = object({ message: "Difficulty should be easy,medium,hard only", } ), - youtube_video_link: string({ - required_error: "youtubeVideoLink is required", + videoLink: string({ + required_error: "videoLink is required", }) .url("should be a url") .nonempty({ message: "youtube link can't be empty" }) .trim() .refine( (value) => { - if (value.includes("https://www.youtube.com/watch?v=")) return true; + if (value.includes("https://")) return true; else return false; }, { - message: "Invalid youtube link format", + message: "Invalid link format", } ), - leet_code_problem_link: string({ - required_error: "leetCodeProblemLink is required", + problemLink: string({ + required_error: "problemLink is required", }) .url("should be a url") .nonempty({ message: "leetcode link can't be empty" }) .trim() .refine( (value) => { - if (value.includes("https://leetcode.com/problems")) return true; + if (value.includes("https://")) return true; else return false; }, { - message: "Invalid leetcode link format", + message: "Invalid link format", } ), - under_which_topic: string({ + underWhichTopic: number({ required_error: "under which topic is required", - }) - .nonempty({ message: "under which topic link can't be empty" }) - .trim() - .refine( - async (topicName) => { - const topic = await TopicUnderSubject.findOne({ - where: { topic_name: topicName }, - }); - if (topic) return true; - else return false; - }, - { message: " Entered topic name does not exists" } - ), + }).refine( + async (topicId) => { + const topic = await TopicUnderSubject.findByPk(topicId); + if (topic) return true; + else return false; + }, + { message: "Entered topicId does not exists" } + ), }), }); export const deleteQuestionSchema = object({ - params: object({ - questionName: string({ required_error: "question_name is required" }) - .nonempty({ message: "name can't be empty" }) - .min(5, "question_name should not be less than 5 characters") - .max(30, "question_name should be not be greater than 30 characters") - .trim() - .refine( - async (questionName) => { - const question = await Question.findOne({ - where: { question_name: questionName }, - }); - if (question) return true; - else return false; - }, - { message: "question_name does not exist" } - ), + body: object({ + questionId: number({ required_error: "questionId is required" }).refine( + async (questionId) => { + const question = await Question.findByPk(questionId); + if (question) return true; + else return false; + }, + { message: "questionId does not exist" } + ), }), }); diff --git a/src/schema/subject.schema.ts b/src/schema/subject.schema.ts index 15a21f2..4f12c54 100644 --- a/src/schema/subject.schema.ts +++ b/src/schema/subject.schema.ts @@ -3,7 +3,7 @@ import { Subject } from "../models/Subject"; export const createSubjectSchema = object({ body: object({ - subject_name: string({ + name: string({ required_error: "subjectName is required", }) .nonempty({ message: "name can't be empty" }) @@ -13,27 +13,27 @@ export const createSubjectSchema = object({ .refine( async (subjectName) => { const subject = await Subject.findOne({ - where: { subject_name: subjectName }, + where: { name: subjectName }, }); if (subject) return false; else return true; }, { message: "Subject already existed" } ), - subject_description: string({ + description: string({ required_error: "subjectDescription is required", }) .nonempty({ message: "description can't be empty" }) .min(5, "subjectDescription should not be less than 5 characters") .max(50, "subjectDescription should not be greater than 50 characters") .trim(), - topic_count: number({ + topicCount: number({ required_error: "topicCount is required", }) .int("topicCount should be a integer") .lt(100, "topicCount should be less than 100") .gt(0, "topicCount should be greater than 0"), - image_url: string({ + imageUrl: string({ required_error: "imageUrl is required", }) .url("imageUrl should be a url") @@ -42,62 +42,60 @@ export const createSubjectSchema = object({ }); export const updateSubjectSchema = object({ - params: object({ - subjectName: string({ required_error: "subject_name is required" }) - .nonempty({ message: "name can't be empty" }) - .min(5, "subjectName should not be less than 5 characters") - .max(30, "subjectName should be not be greater than 30 characters") - .trim() - .refine( - async (subjectName) => { - const subject = await Subject.findOne({ - where: { subject_name: subjectName }, - }); - if (subject) return true; - else return false; - }, - { message: "Subject does not exist" } - ), - }), body: object({ - subject_name: string({ required_error: "subject_name is required" }) + subjectId: string({ required_error: "subjectId is required" }).refine( + async (subjectId) => { + const subject = await Subject.findByPk(subjectId); + console.log(subject); + if (subject) return true; + else return false; + }, + { message: "Subject does not exist" } + ), + name: string({ required_error: "subject_name is required" }) .nonempty({ message: "name can't be empty" }) .min(5, "subjectName should not be less than 5 characters") .max(30, "subjectName should be not be greater than 30 characters") .trim(), - subject_description: string({ + description: string({ required_error: "topic_description is required", }) .nonempty({ message: "description can't be empty" }) .min(5, "subjectDescription should not be less than 5 characters") .max(50, "subjectDescription should not be greater than 50 characters") .trim(), - topic_count: number({ required_error: "topic_count is required" }) + topicCount: number({ required_error: "topic_count is required" }) .int("topicCount should be a integer") .lt(100, "topicCount should be less than 100") .gt(0, "topicCount should be greater than 0"), - image_url: string({ required_error: "image_url is required" }) + imageUrl: string({ required_error: "image_url is required" }) .url("imageUrl should be a url") .trim(), }), }); -export const deleteSubjectSchema = object({ - params: object({ - subjectName: string({ required_error: "subject_name is required" }) - .nonempty({ message: "name can't be empty" }) - .min(5, "subjectName should not be less than 5 characters") - .max(30, "subjectName should be not be greater than 30 characters") - .trim() - .refine( - async (subjectName) => { - const subject = await Subject.findOne({ - where: { subject_name: subjectName }, - }); - if (subject) return true; - else return false; - }, - { message: "Subject does not existed" } - ), +export const getSubjectByIdSchema = object({ + query: object({ + subjectId: number({ required_error: "subjectId is required" }).refine( + async (subjectId) => { + const subject = await Subject.findByPk(subjectId); + if (subject) return true; + else return false; + }, + { message: "Subject does not existed" } + ), + }), +}); + +export const deleteSubjectByIdSchema = object({ + body: object({ + subjectId: string({ required_error: "subjectId is required" }).refine( + async (subjectId) => { + const subject = await Subject.findByPk(subjectId); + if (subject) return true; + else return false; + }, + { message: "Subject does not exist" } + ), }), }); diff --git a/src/schema/topicUnderSubject.schema.ts b/src/schema/topicUnderSubject.schema.ts index 4d5caa3..fe24a2c 100644 --- a/src/schema/topicUnderSubject.schema.ts +++ b/src/schema/topicUnderSubject.schema.ts @@ -4,7 +4,7 @@ import { TopicUnderSubject } from "../models/TopicUnderSubject"; export const createTopicUnderSubjectSchema = object({ body: object({ - topic_name: string({ + name: string({ required_error: "topicName is required", }) .nonempty({ message: "topicName can't be empty" }) @@ -12,125 +12,104 @@ export const createTopicUnderSubjectSchema = object({ .max(30, "topicName should be not be greater than 30 characters") .trim() .refine( - async (topicName) => { + async (name) => { const topic = await TopicUnderSubject.findOne({ - where: { topic_name: topicName }, + where: { name: name }, }); if (topic) return false; else return true; }, { message: "topic name already existed" } ), - topic_description: string({ + description: string({ required_error: "topicDescription is required", }) .nonempty({ message: "topicName can't be empty" }) .min(5, "topicDescription should not be less than 5 characters") .max(50, "topicDescription should not be greater than 50 characters") .trim(), - question_count: number({ + questionCount: number({ required_error: "questionCount is required", }) .int("questionCount should be a integer") .lt(100, "questionCount should be less than 100") .gt(0, "questionCount should be greater than 0"), - under_which_subject: string({ + underWhichSubject: number({ required_error: "underWhichSubject is required", - }) - .nonempty({ message: "under_which_subject can't be empty" }) - .min(5, "under_which_subject should not be less than 5 characters") - .max( - 30, - "under_which_subject should be not be greater than 30 characters" - ) - .trim() - .refine( - async (subjectName) => { - const subject = await Subject.findOne({ - where: { subject_name: subjectName }, - }); - if (subject) return true; - else return false; - }, - { message: "Entered subject name does not exists" } - ), + }).refine( + async (underWhichSubject) => { + const subject = await Subject.findOne({ + where: { id: underWhichSubject }, + }); + if (subject) return true; + else return false; + }, + { message: "Entered subject name does not exists" } + ), }), }); export const updateTopicUnderSubjectSchema = object({ - params: object({ - topicName: string({ required_error: "topic_name is required" }) - .nonempty({ message: "name can't be empty" }) - .min(5, "topic_name should not be less than 5 characters") - .max(30, "topic_name should be not be greater than 30 characters") - .trim() - .refine( - async (topicName) => { - const topic = await TopicUnderSubject.findOne({ - where: { topic_name: topicName }, - }); - if (topic) return true; - else return false; - }, - { message: "topic_name does not exist" } - ), - }), body: object({ - topic_name: string({ required_error: "topic_name is required" }) + topicId: number({ required_error: "topicId is required" }).refine( + async (topicId) => { + const topic = await TopicUnderSubject.findByPk(topicId); + if (topic) return true; + else return false; + }, + { message: "topicId does not exist" } + ), + name: string({ required_error: "topic_name is required" }) .nonempty({ message: "name can't be empty" }) .min(5, "subjectName should not be less than 5 characters") .max(30, "subjectName should be not be greater than 30 characters") .trim(), - topic_description: string({ + description: string({ required_error: "topic_description is required", }) .nonempty({ message: "description can't be empty" }) .min(5, "subjectDescription should not be less than 5 characters") .max(50, "subjectDescription should not be greater than 50 characters") .trim(), - question_count: number({ required_error: "question_count is required" }) + questionCount: number({ required_error: "question_count is required" }) .int("topicCount should be a integer") .lt(100, "topicCount should be less than 100") .gt(0, "topicCount should be greater than 0"), - under_which_subject: string({ + underWhichSubject: number({ required_error: "underWhichSubject is required", - }) - .nonempty({ message: "under_which_subject can't be empty" }) - .min(5, "under_which_subject should not be less than 5 characters") - .max( - 30, - "under_which_subject should be not be greater than 30 characters" - ) - .trim() - .refine( - async (subjectName) => { - const subject = await Subject.findOne({ - where: { subject_name: subjectName }, - }); - if (subject) return true; - else return false; - }, - { message: "Entered subject name does not exists" } - ), + }).refine( + async (underWhichSubject) => { + const subject = await Subject.findByPk(underWhichSubject); + if (subject) return true; + else return false; + }, + { message: "Entered subject id does not exists" } + ), }), }); export const deleteTopicUnderSubjectSchema = object({ - params: object({ - topicName: string({ required_error: "topic_name is required" }) - .nonempty({ message: "name can't be empty" }) - .min(5, "topic_name should not be less than 5 characters") - .max(30, "topic_name should be not be greater than 30 characters") - .trim() - .refine( - async (topicName) => { - const topic = await TopicUnderSubject.findOne({ - where: { topic_name: topicName }, - }); - if (topic) return true; - else return false; - }, - { message: "topic_name does not exist" } - ), + body: object({ + topicId: number({ required_error: "topicId is required" }).refine( + async (topicId) => { + const topic = await TopicUnderSubject.findByPk(topicId); + if (topic) return true; + else return false; + }, + { message: "topic_name does not exist" } + ), + }), +}); + +export const getTopicByIdSchema = object({ + query: object({ + topicId: number({ required_error: "topicId is required" }).refine( + async (topicId) => { + const topic = await TopicUnderSubject.findByPk(topicId); + if (topic) return true; + else return false; + }, + { message: "topic_name does not exist" } + ), }), }); diff --git a/todo.txt b/todo.txt index 9711452..85c4b8f 100644 --- a/todo.txt +++ b/todo.txt @@ -3,6 +3,9 @@ work on all controllers aas models have changed do stronger validation postman collection check any missing todos +check for deletion if topic has question then cant delete it check dal files +rename methods some have byid some dont + add sheets like 450 one stored locally if not logged in cookie management on brave