mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
experimental (unfinished)
This commit is contained in:
parent
265f9a2b76
commit
e710e1a6fe
14 changed files with 536 additions and 277 deletions
|
|
@ -1,64 +1,25 @@
|
||||||
const request = require('supertest');
|
import { Image } from '../models/image';
|
||||||
const app = require('../app.js');
|
import { User } from '../models/user';
|
||||||
// const app = require('../routers/images.js');
|
|
||||||
const { response } = require('express');
|
|
||||||
|
|
||||||
const BASE_URL = '/image'
|
describe('Image', () => {
|
||||||
|
let mockUser: User;
|
||||||
|
|
||||||
describe("POST /upload", () => {
|
beforeEach(() => {
|
||||||
|
mockUser = new User({
|
||||||
|
email: 'test@example.com',
|
||||||
|
hashedPassword: 'hashedPassword123'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("when the jwt is not sent", () => {
|
it('should create an image with the correct properties', () => {
|
||||||
|
const fileName = 'test.png';
|
||||||
|
const fileContent = Buffer.from('test content');
|
||||||
|
const mimeType = 'image/png';
|
||||||
|
const image = new Image(fileName, fileContent, mimeType, mockUser);
|
||||||
|
|
||||||
test('should respond with 401 status code', async () => {
|
expect(image.file_name).toBe(fileName);
|
||||||
const response = await request(app).post(BASE_URL + "/upload").send()
|
expect(image.file_content).toBe(fileContent);
|
||||||
expect(response.statusCode).toBe(401)
|
expect(image.mime_type).toBe(mimeType);
|
||||||
})
|
expect(image.owner).toBe(mockUser);
|
||||||
// respond message Accès refusé. Aucun jeton fourni.
|
});
|
||||||
|
});
|
||||||
})
|
|
||||||
|
|
||||||
describe("when sent bad jwt", () => {
|
|
||||||
// respond with 401
|
|
||||||
// respond message Accès refusé. Jeton invalide.
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when sent no variables", () => {
|
|
||||||
// respond message Paramètre requis manquant.
|
|
||||||
// respond code 400
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when sent not an image file", () => {
|
|
||||||
// respond code 505
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when sent image file", () => {
|
|
||||||
// respond code 200
|
|
||||||
// json content type
|
|
||||||
// test("should reply with content type json", async () => {
|
|
||||||
// const response = await request(app).post(BASE_URL+'/upload').send()
|
|
||||||
// expect(response.headers['content-type']).toEqual(expect.stringContaining('json'))
|
|
||||||
// })
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("GET /get", () => {
|
|
||||||
|
|
||||||
describe("when not give id", () => {
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when not good id", () => {
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("when good id", () => {
|
|
||||||
// respond code 200
|
|
||||||
// image content type
|
|
||||||
// response has something
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
|
||||||
64
server/__tests__/image.test.ts.old
Normal file
64
server/__tests__/image.test.ts.old
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
const request = require('supertest');
|
||||||
|
const app = require('../app.js');
|
||||||
|
// const app = require('../routers/images.js');
|
||||||
|
const { response } = require('express');
|
||||||
|
|
||||||
|
const BASE_URL = '/image'
|
||||||
|
|
||||||
|
describe("POST /upload", () => {
|
||||||
|
|
||||||
|
describe("when the jwt is not sent", () => {
|
||||||
|
|
||||||
|
test('should respond with 401 status code', async () => {
|
||||||
|
const response = await request(app).post(BASE_URL + "/upload").send()
|
||||||
|
expect(response.statusCode).toBe(401)
|
||||||
|
})
|
||||||
|
// respond message Accès refusé. Aucun jeton fourni.
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("when sent bad jwt", () => {
|
||||||
|
// respond with 401
|
||||||
|
// respond message Accès refusé. Jeton invalide.
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("when sent no variables", () => {
|
||||||
|
// respond message Paramètre requis manquant.
|
||||||
|
// respond code 400
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("when sent not an image file", () => {
|
||||||
|
// respond code 505
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("when sent image file", () => {
|
||||||
|
// respond code 200
|
||||||
|
// json content type
|
||||||
|
// test("should reply with content type json", async () => {
|
||||||
|
// const response = await request(app).post(BASE_URL+'/upload').send()
|
||||||
|
// expect(response.headers['content-type']).toEqual(expect.stringContaining('json'))
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("GET /get", () => {
|
||||||
|
|
||||||
|
describe("when not give id", () => {
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("when not good id", () => {
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("when good id", () => {
|
||||||
|
// respond code 200
|
||||||
|
// image content type
|
||||||
|
// response has something
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
@ -27,4 +27,4 @@ class DBConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DBConnection;
|
export default new DBConnection();
|
||||||
|
|
|
||||||
|
|
@ -1,133 +1,110 @@
|
||||||
exports.UNAUTHORIZED_NO_TOKEN_GIVEN = {
|
export const UNAUTHORIZED_NO_TOKEN_GIVEN = {
|
||||||
message: 'Accès refusé. Aucun jeton fourni.',
|
message: 'Accès refusé. Aucun jeton fourni.',
|
||||||
code: 401
|
code: 401
|
||||||
}
|
};
|
||||||
exports.UNAUTHORIZED_INVALID_TOKEN = {
|
export const UNAUTHORIZED_INVALID_TOKEN = {
|
||||||
message: 'Accès refusé. Jeton invalide.',
|
message: 'Accès refusé. Jeton invalide.',
|
||||||
code: 401
|
code: 401
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.MISSING_REQUIRED_PARAMETER = {
|
export const MISSING_REQUIRED_PARAMETER = {
|
||||||
message: 'Paramètre requis manquant.',
|
message: 'Paramètre requis manquant.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.USER_ALREADY_EXISTS = {
|
export const USER_ALREADY_EXISTS = {
|
||||||
message: 'L\'utilisateur existe déjà.',
|
message: 'L\'utilisateur existe déjà.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.LOGIN_CREDENTIALS_ERROR = {
|
export const LOGIN_CREDENTIALS_ERROR = {
|
||||||
message: 'L\'email et le mot de passe ne correspondent pas.',
|
message: 'L\'email et le mot de passe ne correspondent pas.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.GENERATE_PASSWORD_ERROR = {
|
export const GENERATE_PASSWORD_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la création d\'un nouveau mot de passe.',
|
message: 'Une erreur s\'est produite lors de la création d\'un nouveau mot de passe.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.UPDATE_PASSWORD_ERROR = {
|
export const UPDATE_PASSWORD_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la mise à jours du mot de passe.',
|
message: 'Une erreur s\'est produite lors de la mise à jours du mot de passe.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.DELETE_USER_ERROR = {
|
export const DELETE_USER_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de supression de l\'utilisateur.',
|
message: 'Une erreur s\'est produite lors de suppression de l\'utilisateur.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.IMAGE_NOT_FOUND = {
|
export const IMAGE_NOT_FOUND = {
|
||||||
message: 'Nous n\'avons pas trouvé l\'image.',
|
message: 'Nous n\'avons pas trouvé l\'image.',
|
||||||
code: 404
|
code: 404
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.QUIZ_NOT_FOUND = {
|
export const QUIZ_NOT_FOUND = {
|
||||||
message: 'Aucun quiz portant cet identifiant n\'a été trouvé.',
|
message: 'Aucun quiz portant cet identifiant n\'a été trouvé.',
|
||||||
code: 404
|
code: 404
|
||||||
}
|
};
|
||||||
exports.QUIZ_ALREADY_EXISTS = {
|
export const QUIZ_ALREADY_EXISTS = {
|
||||||
message: 'Le quiz existe déja.',
|
message: 'Le quiz existe déjà.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.UPDATE_QUIZ_ERROR = {
|
export const UPDATE_QUIZ_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la mise à jours du quiz.',
|
message: 'Une erreur s\'est produite lors de la mise à jours du quiz.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.DELETE_QUIZ_ERROR = {
|
export const DELETE_QUIZ_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la supression du quiz.',
|
message: 'Une erreur s\'est produite lors de la suppression du quiz.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.GETTING_QUIZ_ERROR = {
|
export const GETTING_QUIZ_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la récupération du quiz.',
|
message: 'Une erreur s\'est produite lors de la récupération du quiz.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.MOVING_QUIZ_ERROR = {
|
export const MOVING_QUIZ_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors du déplacement du quiz.',
|
message: 'Une erreur s\'est produite lors du déplacement du quiz.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.DUPLICATE_QUIZ_ERROR = {
|
export const DUPLICATE_QUIZ_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la duplication du quiz.',
|
message: 'Une erreur s\'est produite lors de la duplication du quiz.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.COPY_QUIZ_ERROR = {
|
export const COPY_QUIZ_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la copie du quiz.',
|
message: 'Une erreur s\'est produite lors de la copie du quiz.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
|
|
||||||
exports.FOLDER_NOT_FOUND = {
|
export const FOLDER_NOT_FOUND = {
|
||||||
message: 'Aucun dossier portant cet identifiant n\'a été trouvé.',
|
message: 'Aucun dossier portant cet identifiant n\'a été trouvé.',
|
||||||
code: 404
|
code: 404
|
||||||
}
|
};
|
||||||
exports.FOLDER_ALREADY_EXISTS = {
|
export const FOLDER_ALREADY_EXISTS = {
|
||||||
message: 'Le dossier existe déja.',
|
message: 'Le dossier existe déjà.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.UPDATE_FOLDER_ERROR = {
|
export const UPDATE_FOLDER_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la mise à jours du dossier.',
|
message: 'Une erreur s\'est produite lors de la mise à jours du dossier.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.DELETE_FOLDER_ERROR = {
|
export const DELETE_FOLDER_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la supression du dossier.',
|
message: 'Une erreur s\'est produite lors de la suppression du dossier.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.GETTING_FOLDER_ERROR = {
|
export const GETTING_FOLDER_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la récupération du dossier.',
|
message: 'Une erreur s\'est produite lors de la récupération du dossier.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.MOVING_FOLDER_ERROR = {
|
export const MOVING_FOLDER_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors du déplacement du dossier.',
|
message: 'Une erreur s\'est produite lors du déplacement du dossier.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.DUPLICATE_FOLDER_ERROR = {
|
export const DUPLICATE_FOLDER_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la duplication du dossier.',
|
message: 'Une erreur s\'est produite lors de la duplication du dossier.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
exports.COPY_FOLDER_ERROR = {
|
export const COPY_FOLDER_ERROR = {
|
||||||
message: 'Une erreur s\'est produite lors de la copie du dossier.',
|
message: 'Une erreur s\'est produite lors de la copie du dossier.',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const NOT_IMPLEMENTED = {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.NOT_IMPLEMENTED = {
|
|
||||||
message: 'Route not implemented yet!',
|
message: 'Route not implemented yet!',
|
||||||
code: 400
|
code: 400
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
// static ok(res, results) {200
|
|
||||||
// static badRequest(res, message) {400
|
|
||||||
// static unauthorized(res, message) {401
|
|
||||||
// static notFound(res, message) {404
|
|
||||||
// static serverError(res, message) {505
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,22 @@
|
||||||
const model = require('../models/quiz.js');
|
import { Request, Response, NextFunction } from 'express';
|
||||||
const folderModel = require('../models/folders.js');
|
import AppError from '../middleware/AppError';
|
||||||
const emailer = require('../config/email.js');
|
import { MISSING_REQUIRED_PARAMETER, NOT_IMPLEMENTED, QUIZ_NOT_FOUND, FOLDER_NOT_FOUND, QUIZ_ALREADY_EXISTS, GETTING_QUIZ_ERROR, DELETE_QUIZ_ERROR, UPDATE_QUIZ_ERROR, MOVING_QUIZ_ERROR } from '../constants/errorCodes';
|
||||||
|
import { Quiz } from '../models/quiz';
|
||||||
const AppError = require('../middleware/AppError.js');
|
import { Folder } from '../models/folder';
|
||||||
const { MISSING_REQUIRED_PARAMETER, NOT_IMPLEMENTED, QUIZ_NOT_FOUND, FOLDER_NOT_FOUND, QUIZ_ALREADY_EXISTS, GETTING_QUIZ_ERROR, DELETE_QUIZ_ERROR, UPDATE_QUIZ_ERROR, MOVING_QUIZ_ERROR, DUPLICATE_QUIZ_ERROR, COPY_QUIZ_ERROR } = require('../constants/errorCodes');
|
import Emailer from '../config/email';
|
||||||
|
|
||||||
class QuizController {
|
class QuizController {
|
||||||
|
private quiz: Quiz;
|
||||||
|
private folder: Folder;
|
||||||
|
private emailer: Emailer;
|
||||||
|
|
||||||
async create(req, res, next) {
|
constructor() {
|
||||||
|
this.folder = new Folder();
|
||||||
|
this.quiz = new Quiz();
|
||||||
|
this.emailer = new Emailer();
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(req: Request, res: Response, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const { title, content, folderId } = req.body;
|
const { title, content, folderId } = req.body;
|
||||||
|
|
||||||
|
|
@ -16,13 +25,13 @@ class QuizController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this folder mine
|
// Is this folder mine
|
||||||
const owner = await folderModel.getOwner(folderId);
|
const owner = await this.folder.getOwner(folderId);
|
||||||
|
|
||||||
if (owner != req.user.userId) {
|
if (owner != req.user.userId) {
|
||||||
throw new AppError(FOLDER_NOT_FOUND);
|
throw new AppError(FOLDER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await model.create(title, content, folderId, req.user.userId);
|
const result = await this.quiz.create(title, content, folderId, req.user.userId);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new AppError(QUIZ_ALREADY_EXISTS);
|
throw new AppError(QUIZ_ALREADY_EXISTS);
|
||||||
|
|
@ -38,7 +47,7 @@ class QuizController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(req, res, next) {
|
async get(req: Request, res: Response, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const { quizId } = req.params;
|
const { quizId } = req.params;
|
||||||
|
|
||||||
|
|
@ -47,7 +56,7 @@ class QuizController {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const content = await model.getContent(quizId);
|
const content = await this.quiz.getContent(quizId);
|
||||||
|
|
||||||
if (!content) {
|
if (!content) {
|
||||||
throw new AppError(GETTING_QUIZ_ERROR);
|
throw new AppError(GETTING_QUIZ_ERROR);
|
||||||
|
|
@ -68,7 +77,7 @@ class QuizController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(req, res, next) {
|
async delete(req: Request, res: Response, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const { quizId } = req.params;
|
const { quizId } = req.params;
|
||||||
|
|
||||||
|
|
@ -77,13 +86,13 @@ class QuizController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this quiz mine
|
// Is this quiz mine
|
||||||
const owner = await model.getOwner(quizId);
|
const owner = await this.quiz.getOwner(quizId);
|
||||||
|
|
||||||
if (owner != req.user.userId) {
|
if (owner != req.user.userId) {
|
||||||
throw new AppError(QUIZ_NOT_FOUND);
|
throw new AppError(QUIZ_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await model.delete(quizId);
|
const result = await this.quiz.delete(quizId);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new AppError(DELETE_QUIZ_ERROR);
|
throw new AppError(DELETE_QUIZ_ERROR);
|
||||||
|
|
@ -99,7 +108,7 @@ class QuizController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(req, res, next) {
|
async update(req: Request, res: Response, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const { quizId, newTitle, newContent } = req.body;
|
const { quizId, newTitle, newContent } = req.body;
|
||||||
|
|
||||||
|
|
@ -108,13 +117,13 @@ class QuizController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this quiz mine
|
// Is this quiz mine
|
||||||
const owner = await model.getOwner(quizId);
|
const owner = await this.quiz.getOwner(quizId);
|
||||||
|
|
||||||
if (owner != req.user.userId) {
|
if (owner != req.user.userId) {
|
||||||
throw new AppError(QUIZ_NOT_FOUND);
|
throw new AppError(QUIZ_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await model.update(quizId, newTitle, newContent);
|
const result = await this.quiz.update(quizId, newTitle, newContent);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new AppError(UPDATE_QUIZ_ERROR);
|
throw new AppError(UPDATE_QUIZ_ERROR);
|
||||||
|
|
@ -130,7 +139,7 @@ class QuizController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async move(req, res, next) {
|
async move(req: Request, res: Response, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const { quizId, newFolderId } = req.body;
|
const { quizId, newFolderId } = req.body;
|
||||||
|
|
||||||
|
|
@ -139,20 +148,20 @@ class QuizController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this quiz mine
|
// Is this quiz mine
|
||||||
const quizOwner = await model.getOwner(quizId);
|
const quizOwner = await this.quiz.getOwner(quizId);
|
||||||
|
|
||||||
if (quizOwner != req.user.userId) {
|
if (quizOwner != req.user.userId) {
|
||||||
throw new AppError(QUIZ_NOT_FOUND);
|
throw new AppError(QUIZ_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this folder mine
|
// Is this folder mine
|
||||||
const folderOwner = await folderModel.getOwner(newFolderId);
|
const folderOwner = await this.folder.getOwner(newFolderId);
|
||||||
|
|
||||||
if (folderOwner != req.user.userId) {
|
if (folderOwner != req.user.userId) {
|
||||||
throw new AppError(FOLDER_NOT_FOUND);
|
throw new AppError(FOLDER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await model.move(quizId, newFolderId);
|
const result = await this.quiz.move(quizId, newFolderId);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new AppError(MOVING_QUIZ_ERROR);
|
throw new AppError(MOVING_QUIZ_ERROR);
|
||||||
|
|
@ -169,8 +178,7 @@ class QuizController {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async copy(req: Request, res: Response, next: NextFunction) {
|
||||||
async copy(req, res, next) {
|
|
||||||
const { quizId, newTitle, folderId } = req.body;
|
const { quizId, newTitle, folderId } = req.body;
|
||||||
|
|
||||||
if (!quizId || !newTitle || !folderId) {
|
if (!quizId || !newTitle || !folderId) {
|
||||||
|
|
@ -178,32 +186,9 @@ class QuizController {
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new AppError(NOT_IMPLEMENTED);
|
throw new AppError(NOT_IMPLEMENTED);
|
||||||
// const { quizId } = req.params;
|
|
||||||
// const { newUserId } = req.body;
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// //Trouver le quiz a dupliquer
|
|
||||||
// const conn = db.getConnection();
|
|
||||||
// const quiztoduplicate = await conn.collection('quiz').findOne({ _id: new ObjectId(quizId) });
|
|
||||||
// if (!quiztoduplicate) {
|
|
||||||
// throw new Error("Quiz non trouvé");
|
|
||||||
// }
|
|
||||||
// console.log(quiztoduplicate);
|
|
||||||
// //Suppression du id du quiz pour ne pas le répliquer
|
|
||||||
// delete quiztoduplicate._id;
|
|
||||||
// //Ajout du duplicata
|
|
||||||
// await conn.collection('quiz').insertOne({ ...quiztoduplicate, userId: new ObjectId(newUserId) });
|
|
||||||
// res.json(Response.ok("Dossier dupliqué avec succès pour un autre utilisateur"));
|
|
||||||
|
|
||||||
// } catch (error) {
|
|
||||||
// if (error.message.startsWith("Quiz non trouvé")) {
|
|
||||||
// return res.status(404).json(Response.badRequest(error.message));
|
|
||||||
// }
|
|
||||||
// res.status(500).json(Response.serverError(error.message));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteQuizzesByFolderId(req, res, next) {
|
async deleteQuizzesByFolderId(req: Request, res: Response, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const { folderId } = req.body;
|
const { folderId } = req.body;
|
||||||
|
|
||||||
|
|
@ -212,7 +197,7 @@ class QuizController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the method from the Quiz model to delete quizzes by folder ID
|
// Call the method from the Quiz model to delete quizzes by folder ID
|
||||||
await Quiz.deleteQuizzesByFolderId(folderId);
|
await this.quiz.deleteQuizzesByFolderId(folderId);
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
message: 'Quizzes deleted successfully.'
|
message: 'Quizzes deleted successfully.'
|
||||||
|
|
@ -222,27 +207,27 @@ class QuizController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async duplicate(req, res, next) {
|
async duplicate(req: Request, res: Response, next: NextFunction) {
|
||||||
const { quizId } = req.body;
|
const { quizId } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const newQuizId = await model.duplicate(quizId,req.user.userId);
|
const newQuizId = await this.quiz.duplicate(quizId, req.user.userId);
|
||||||
res.status(200).json({ success: true, newQuizId });
|
res.status(200).json({ success: true, newQuizId });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return next(error);
|
return next(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async quizExists(title, userId) {
|
async quizExists(title: string, userId: string) {
|
||||||
try {
|
try {
|
||||||
const existingFile = await model.quizExists(title, userId);
|
const existingFile = await this.quiz.quizExists(title, userId);
|
||||||
return existingFile !== null;
|
return existingFile !== null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new AppError(GETTING_QUIZ_ERROR);
|
throw new AppError(GETTING_QUIZ_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async Share(req, res, next) {
|
async Share(req: Request, res: Response, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const { quizId, email } = req.body;
|
const { quizId, email } = req.body;
|
||||||
|
|
||||||
|
|
@ -252,7 +237,7 @@ class QuizController {
|
||||||
|
|
||||||
const link = `${process.env.FRONTEND_URL}/teacher/Share/${quizId}`;
|
const link = `${process.env.FRONTEND_URL}/teacher/Share/${quizId}`;
|
||||||
|
|
||||||
emailer.quizShare(email, link);
|
this.emailer.quizShare(email, link);
|
||||||
|
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
message: 'Quiz partagé avec succès.'
|
message: 'Quiz partagé avec succès.'
|
||||||
|
|
@ -264,7 +249,7 @@ class QuizController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getShare(req, res, next) {
|
async getShare(req: Request, res: Response, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const { quizId } = req.params;
|
const { quizId } = req.params;
|
||||||
|
|
||||||
|
|
@ -272,7 +257,7 @@ class QuizController {
|
||||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = await model.getContent(quizId);
|
const content = await this.quiz.getContent(quizId);
|
||||||
|
|
||||||
if (!content) {
|
if (!content) {
|
||||||
throw new AppError(GETTING_QUIZ_ERROR);
|
throw new AppError(GETTING_QUIZ_ERROR);
|
||||||
|
|
@ -288,7 +273,7 @@ class QuizController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async receiveShare(req, res, next) {
|
async receiveShare(req: Request, res: Response, next: NextFunction) {
|
||||||
try {
|
try {
|
||||||
const { quizId, folderId } = req.body;
|
const { quizId, folderId } = req.body;
|
||||||
|
|
||||||
|
|
@ -296,17 +281,17 @@ class QuizController {
|
||||||
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
throw new AppError(MISSING_REQUIRED_PARAMETER);
|
||||||
}
|
}
|
||||||
|
|
||||||
const folderOwner = await folderModel.getOwner(folderId);
|
const folderOwner = await this.folder.getOwner(folderId);
|
||||||
if (folderOwner != req.user.userId) {
|
if (folderOwner != req.user.userId) {
|
||||||
throw new AppError(FOLDER_NOT_FOUND);
|
throw new AppError(FOLDER_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = await model.getContent(quizId);
|
const content = await this.quiz.getContent(quizId);
|
||||||
if (!content) {
|
if (!content) {
|
||||||
throw new AppError(GETTING_QUIZ_ERROR);
|
throw new AppError(GETTING_QUIZ_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await model.create(content.title, content.content, folderId, req.user.userId);
|
const result = await this.quiz.create(content.title, content.content, folderId, req.user.userId);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new AppError(QUIZ_ALREADY_EXISTS);
|
throw new AppError(QUIZ_ALREADY_EXISTS);
|
||||||
}
|
}
|
||||||
|
|
@ -319,8 +304,6 @@ class QuizController {
|
||||||
return next(error);
|
return next(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new QuizController;
|
export default new QuizController();
|
||||||
|
|
|
||||||
23
server/docs/addFolder-RDCU.puml
Normal file
23
server/docs/addFolder-RDCU.puml
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
@startuml addFolder-RDCU
|
||||||
|
skinparam style strictuml
|
||||||
|
skinparam SequenceMessageAlignment center
|
||||||
|
|
||||||
|
participant ":Folder\nController" as FC
|
||||||
|
participant ":Évalue\nTon\nSavoir" as ETS
|
||||||
|
participant ":Map<string, User>" as MUS
|
||||||
|
participant "user:User" as U
|
||||||
|
participant "f:Folder" as F
|
||||||
|
|
||||||
|
-> FC: addFolder(folderName: string,\nuserId: string)
|
||||||
|
FC -> ETS : user = getUser(userId: string)
|
||||||
|
note right: by Expert
|
||||||
|
ETS -> MUS : user = find(userId)
|
||||||
|
note right: id to object
|
||||||
|
FC -> ETS : f = createFolder(folderName: string,\nuser: User)
|
||||||
|
create F
|
||||||
|
ETS -->> F : <<create>>
|
||||||
|
note right: by Creator (ETS\naggregates Folder)
|
||||||
|
ETS -> U : addFolder(f)
|
||||||
|
note right: by Expert
|
||||||
|
|
||||||
|
@enduml
|
||||||
38
server/docs/addFolder-serviceLayer.puml
Normal file
38
server/docs/addFolder-serviceLayer.puml
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
@startuml
|
||||||
|
skinparam style strictuml
|
||||||
|
participant ":Folder\nController" as FC
|
||||||
|
participant ":Évalue\nTon\nSavoir" as ETS
|
||||||
|
participant ":Map<string, User>" as MUS
|
||||||
|
participant "user:User" as U
|
||||||
|
participant "f:Folder" as F
|
||||||
|
participant "FolderService" as FS
|
||||||
|
participant "UserRepository" as UR
|
||||||
|
participant "FolderRepository" as FR
|
||||||
|
database "Database" as DB
|
||||||
|
|
||||||
|
-> FC: addFolder(folderName: string,\nuserId: string)
|
||||||
|
FC -> ETS : user = getUser(userId: string)
|
||||||
|
note right: by Expert
|
||||||
|
ETS -> MUS : user = find(userId)
|
||||||
|
note right: id to object
|
||||||
|
FC -> ETS : f = createFolder(folderName: string,\nuser: User)
|
||||||
|
create F
|
||||||
|
ETS -->> F : <<create>>
|
||||||
|
note right: by Creator (ETS\naggregates Folder)
|
||||||
|
ETS -> U : addFolder(f)
|
||||||
|
note right: by Expert
|
||||||
|
|
||||||
|
ETS -> FS: addFolderToUser(user, f)
|
||||||
|
FS -> FR: save(f)
|
||||||
|
FR -> DB: insertOne(f)
|
||||||
|
DB --> FR: insertedId
|
||||||
|
FR --> FS: save result
|
||||||
|
|
||||||
|
FS -> UR: update(user)
|
||||||
|
UR -> DB: updateOne({ _id: user._id }, { $set: { folders: user.folders } })
|
||||||
|
DB --> UR: update result
|
||||||
|
UR --> FS: update result
|
||||||
|
|
||||||
|
FS --> ETS: success
|
||||||
|
ETS --> FC: success
|
||||||
|
@enduml
|
||||||
34
server/docs/mdd.puml
Normal file
34
server/docs/mdd.puml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
@startuml MDD EvalueTonSavoir
|
||||||
|
skinparam style strictuml
|
||||||
|
hide empty members
|
||||||
|
|
||||||
|
class "EvalueTonSavoir" as ETS
|
||||||
|
|
||||||
|
class User {
|
||||||
|
id: string
|
||||||
|
email: string
|
||||||
|
hashedPassword: string
|
||||||
|
createdAt: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
class Quiz {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
content: string
|
||||||
|
createdAt: Date
|
||||||
|
updatedAt: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
class Folder {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
createdAt: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
User "1" -- "1..*" Folder : Creates >
|
||||||
|
Folder "1" *-- "1..*" Quiz : Contains >
|
||||||
|
User "1" *-- "1..*" Quiz : Creates >
|
||||||
|
ETS "1" *-- "1..*" User : Contains >
|
||||||
|
ETS "1" *-- "1..*" Folder : Contains >
|
||||||
|
ETS "1" *-- "1..*" Quiz : Contains >
|
||||||
|
@enduml
|
||||||
|
|
@ -1,8 +1,16 @@
|
||||||
|
interface ErrorCode {
|
||||||
|
message: string;
|
||||||
|
code: number;
|
||||||
|
}
|
||||||
|
|
||||||
class AppError extends Error {
|
class AppError extends Error {
|
||||||
constructor (errorCode) {
|
statusCode: number;
|
||||||
super(errorCode.message)
|
|
||||||
|
constructor(errorCode: ErrorCode) {
|
||||||
|
super(errorCode.message);
|
||||||
this.statusCode = errorCode.code;
|
this.statusCode = errorCode.code;
|
||||||
|
Object.setPrototypeOf(this, AppError.prototype); // Ensure the prototype chain is correctly set
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AppError;
|
export default AppError;
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,35 @@
|
||||||
const jwt = require('jsonwebtoken')
|
import jwt from 'jsonwebtoken';
|
||||||
const dotenv = require('dotenv')
|
import dotenv from 'dotenv';
|
||||||
const AppError = require('./AppError.js');
|
import AppError from './AppError';
|
||||||
const { UNAUTHORIZED_NO_TOKEN_GIVEN, UNAUTHORIZED_INVALID_TOKEN } = require('../constants/errorCodes');
|
import { UNAUTHORIZED_NO_TOKEN_GIVEN, UNAUTHORIZED_INVALID_TOKEN } from '../constants/errorCodes';
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
class Token {
|
class Token {
|
||||||
|
create(email: string, userId: string): string {
|
||||||
create(email, userId) {
|
return jwt.sign({ email, userId }, process.env.JWT_SECRET as string, { expiresIn: '2h' });
|
||||||
return jwt.sign({ email, userId }, process.env.JWT_SECRET);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
authenticate(req, res, next) {
|
authenticate(req: Request, res: Response, next: NextFunction): void {
|
||||||
try {
|
try {
|
||||||
const token = req.header('Authorization') && req.header('Authorization').split(' ')[1];
|
const authHeader = req.header('Authorization');
|
||||||
|
const token = authHeader && authHeader.split(' ')[1];
|
||||||
if (!token) {
|
if (!token) {
|
||||||
throw new AppError(UNAUTHORIZED_NO_TOKEN_GIVEN);
|
throw new AppError(UNAUTHORIZED_NO_TOKEN_GIVEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
jwt.verify(token, process.env.JWT_SECRET, (error, payload) => {
|
jwt.verify(token, process.env.JWT_SECRET as string, (error, payload) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
throw new AppError(UNAUTHORIZED_INVALID_TOKEN)
|
throw new AppError(UNAUTHORIZED_INVALID_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
req.user = payload;
|
req.user = payload;
|
||||||
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return next();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new Token();
|
export default new Token();
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,12 @@
|
||||||
import db from '../config/db';
|
import { User } from "./user";
|
||||||
import { ObjectId } from 'mongodb';
|
|
||||||
|
|
||||||
export class Image {
|
export class Image {
|
||||||
async upload(file: Express.Multer.File, userId: string): Promise<string> {
|
|
||||||
await db.connect();
|
|
||||||
const conn = db.getConnection();
|
|
||||||
|
|
||||||
const imagesCollection = conn.collection('images');
|
constructor(public file_name: string, public file_content: Buffer, public mime_type: string, public owner: User) {
|
||||||
|
this.file_name = file_name;
|
||||||
const newImage = {
|
this.file_content = file_content;
|
||||||
userId: userId,
|
this.mime_type = mime_type;
|
||||||
file_name: file.originalname,
|
this.owner = owner;
|
||||||
file_content: file.buffer.toString('base64'),
|
|
||||||
mime_type: file.mimetype,
|
|
||||||
created_at: new Date(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await imagesCollection.insertOne(newImage);
|
|
||||||
|
|
||||||
return result.insertedId.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(id: string): Promise<{ file_name: string; file_content: Buffer; mime_type: string } | null> {
|
|
||||||
await db.connect();
|
|
||||||
const conn = db.getConnection();
|
|
||||||
|
|
||||||
const imagesCollection = conn.collection('images');
|
|
||||||
|
|
||||||
const result = await imagesCollection.findOne({ _id: new ObjectId(id) });
|
|
||||||
|
|
||||||
if (!result) return null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
file_name: result.file_name,
|
|
||||||
file_content: Buffer.from(result.file_content, 'base64'),
|
|
||||||
mime_type: result.mime_type,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export default new Image();
|
|
||||||
|
|
|
||||||
139
server/repositories/folderRepository.ts
Normal file
139
server/repositories/folderRepository.ts
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
import { Db, ObjectId } from 'mongodb';
|
||||||
|
import DBConnection from '../config/db';
|
||||||
|
import { Folder } from '../models/folder';
|
||||||
|
|
||||||
|
class FolderRepository {
|
||||||
|
private db: DBConnection;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.db = new DBConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
async createFolder(folder: Folder): Promise<ObjectId | null> {
|
||||||
|
await this.db.connect();
|
||||||
|
const conn: Db = this.db.getConnection();
|
||||||
|
|
||||||
|
const folderCollection = conn.collection('folders');
|
||||||
|
|
||||||
|
const existingFolder = await folderCollection.findOne({ title: folder.title, userId: folder.userId });
|
||||||
|
|
||||||
|
if (existingFolder) throw new Error('Dossier existe déjà.');
|
||||||
|
|
||||||
|
const result = await folderCollection.insertOne(folder);
|
||||||
|
return result.insertedId;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUserFolders(userId: string): Promise<any[]> {
|
||||||
|
await db.connect();
|
||||||
|
const conn = db.getConnection();
|
||||||
|
|
||||||
|
const foldersCollection = conn.collection('folders');
|
||||||
|
|
||||||
|
const result = await foldersCollection.find({ userId }).toArray();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async getOwner(folderId: string): Promise<string | null> {
|
||||||
|
await this.db.connect();
|
||||||
|
const conn: Db = this.db.getConnection();
|
||||||
|
|
||||||
|
const folderCollection = conn.collection('folders');
|
||||||
|
|
||||||
|
const folder = await folderCollection.findOne({ _id: new ObjectId(folderId) });
|
||||||
|
|
||||||
|
if (!folder) throw new Error('Dossier non trouvé.');
|
||||||
|
|
||||||
|
return folder.userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getContent(folderId: string): Promise<any[]> {
|
||||||
|
await this.db.connect();
|
||||||
|
const conn: Db = this.db.getConnection();
|
||||||
|
|
||||||
|
const filesCollection = conn.collection('files');
|
||||||
|
|
||||||
|
const result = await filesCollection.find({ folderId }).toArray();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(folderId: string): Promise<boolean> {
|
||||||
|
await this.db.connect();
|
||||||
|
const conn: Db = this.db.getConnection();
|
||||||
|
|
||||||
|
const folderCollection = conn.collection('folders');
|
||||||
|
|
||||||
|
// can't delete a folder if it has quizzes in it
|
||||||
|
const filesCollection = conn.collection('files');
|
||||||
|
const quizzes = await filesCollection.find({ folderId }).toArray();
|
||||||
|
if (quizzes.length > 0) throw new Error('Dossier non vide.');
|
||||||
|
|
||||||
|
const result = await folderCollection.deleteOne({ _id: new ObjectId(folderId) });
|
||||||
|
|
||||||
|
return result.deletedCount === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// async deleteQuizzes(folderId: string): Promise<number> {
|
||||||
|
// await this.db.connect();
|
||||||
|
// const conn: Db = this.db.getConnection();
|
||||||
|
|
||||||
|
// const quizCollection = conn.collection('files');
|
||||||
|
|
||||||
|
// const result = await quizCollection.deleteMany({ folderId: folderId });
|
||||||
|
// return result.deletedCount || 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
async rename(folderId: string, newTitle: string): Promise<boolean> {
|
||||||
|
await this.db.connect();
|
||||||
|
const conn: Db = this.db.getConnection();
|
||||||
|
|
||||||
|
const folderCollection = conn.collection('folders');
|
||||||
|
|
||||||
|
const result = await folderCollection.updateOne(
|
||||||
|
{ _id: new ObjectId(folderId) },
|
||||||
|
{ $set: { title: newTitle } }
|
||||||
|
);
|
||||||
|
|
||||||
|
return result.modifiedCount === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
async duplicate(folderId: string): Promise<ObjectId | null> {
|
||||||
|
const sourceFolder = await this.getFolderWithContent(folderId);
|
||||||
|
|
||||||
|
let newFolderTitle = `${sourceFolder.title}-copie`;
|
||||||
|
let counter = 1;
|
||||||
|
|
||||||
|
while (await sourceFolder.folderExists(newFolderTitle, sourceFolder.userId)) {
|
||||||
|
newFolderTitle = `${sourceFolder.title}-copie(${counter})`;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newFolderId = await this.createFolder(newFolderTitle);
|
||||||
|
|
||||||
|
if (!newFolderId) {
|
||||||
|
throw new Error('Failed to create a duplicate folder.');
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const quiz of sourceFolder.content) {
|
||||||
|
const { title, content } = quiz;
|
||||||
|
await Quiz.create(title, content, newFolderId.toString(), userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newFolderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
async quizExists(title: string, userId: string): Promise<boolean> {
|
||||||
|
await this.db.connect();
|
||||||
|
const conn: Db = this.db.getConnection();
|
||||||
|
|
||||||
|
const quizCollection = conn.collection('files');
|
||||||
|
|
||||||
|
const existingQuiz = await quizCollection.findOne({ title: title, userId: userId });
|
||||||
|
|
||||||
|
return existingQuiz !== null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default QuizRepository;
|
||||||
42
server/services/imageService.ts
Normal file
42
server/services/imageService.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import db from '../config/db';
|
||||||
|
import { ObjectId } from 'mongodb';
|
||||||
|
|
||||||
|
export class Image {
|
||||||
|
async upload(file: Express.Multer.File, userId: string): Promise<string> {
|
||||||
|
await db.connect();
|
||||||
|
const conn = db.getConnection();
|
||||||
|
|
||||||
|
const imagesCollection = conn.collection('images');
|
||||||
|
|
||||||
|
const newImage = {
|
||||||
|
userId: userId,
|
||||||
|
file_name: file.originalname,
|
||||||
|
file_content: file.buffer.toString('base64'),
|
||||||
|
mime_type: file.mimetype,
|
||||||
|
created_at: new Date(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await imagesCollection.insertOne(newImage);
|
||||||
|
|
||||||
|
return result.insertedId.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(id: string): Promise<{ file_name: string; file_content: Buffer; mime_type: string } | null> {
|
||||||
|
await db.connect();
|
||||||
|
const conn = db.getConnection();
|
||||||
|
|
||||||
|
const imagesCollection = conn.collection('images');
|
||||||
|
|
||||||
|
const result = await imagesCollection.findOne({ _id: new ObjectId(id) });
|
||||||
|
|
||||||
|
if (!result) return null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
file_name: result.file_name,
|
||||||
|
file_content: Buffer.from(result.file_content, 'base64'),
|
||||||
|
mime_type: result.mime_type,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new Image();
|
||||||
22
server/services/quizService.ts
Normal file
22
server/services/quizService.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { QuizRepository } from '../repositories/quizRepository';
|
||||||
|
import { Quiz } from '../models/quiz';
|
||||||
|
|
||||||
|
// define a parameter object for the createQuiz method
|
||||||
|
interface CreateQuizParams {
|
||||||
|
title: string;
|
||||||
|
content: string;
|
||||||
|
folder: Folder;
|
||||||
|
user: User;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class QuizService {
|
||||||
|
constructor(private quizRepository: QuizRepository) {}
|
||||||
|
|
||||||
|
async createQuiz(params: CreateQuizParams): Promise<Quiz> {
|
||||||
|
// Create a new Quiz object without an ID
|
||||||
|
const quiz = new Quiz(params.folder, params.user, params.title, params.content);
|
||||||
|
|
||||||
|
// Save the quiz to the database, and the repository assigns the ID
|
||||||
|
return this.quizRepository.save(quiz);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue