WikiLerni/controllers/illustration.js

238 lines
9.4 KiB
JavaScript

const sharp = require("sharp");
const config = require("../config/main.js");
const configIllustrations = require("../config/illustrations.js");
const tool = require("../tools/main");
const toolError = require("../tools/error");
const toolFile = require("../tools/file");
const questionnaireCtrl = require("./questionnaire");
const txt = require("../lang/"+config.adminLang+"/illustration");
const txtGeneral = require("../lang/"+config.adminLang+"/general");
exports.create = async (req, res, next) =>
{
try
{
const db = require("../models/index");
const illustrationDatas = await checkHasFile(req);
// Le fichier peut avoir été bloqué par multer :
if(!illustrationDatas.url)
res.status(400).json({ errors: [txt.needGoodFile] });
else
{
const questionnaire=await questionnaireCtrl.searchQuestionnaireById(illustrationDatas.QuestionnaireId);
if(!questionnaire)
{
toolFile.deleteFile(configIllustrations.dirIllustrations, illustrationDatas.url);
throw { message: txt.needQuestionnaireForIllustration };
}
else if(config.nbIllustrationsMax!==0 && questionnaire.Illustrations.length >= config.nbIllustrationsMax)
{
toolFile.deleteFile(configIllustrations.dirIllustrations, illustrationDatas.url);
res.status(400).json({ errors: [txt.needMaxIllustrationsForQuestionnaire] });
}
else
{
const illustration=await db["Illustration"].create({ ...illustrationDatas }, { fields: ["url", "alt", "title", "caption", "QuestionnaireId"] });
const questionnaireDatas=await questionnaireCtrl.creaQuestionnaireJson(illustrationDatas.QuestionnaireId);// me permet de retourner en réponse les infos actualisées pour les afficher
res.status(201).json({ message: txt.addedOkMessage, questionnaire: questionnaireDatas });
}
}
next();
}
catch(e)
{
const returnAPI=toolError.returnSequelize(e);
if(returnAPI.messages)
{
res.status(returnAPI.status).json({ errors : returnAPI.messages });
next();
}
else
next(e);
}
}
exports.modify = async (req, res, next) =>
{
try
{
const db = require("../models/index");
const illustration=await searchIllustrationById(req.params.id);
if(!illustration)
res.status(404).json({ errors: txt.notFound });
else
{
const questionnaire=await questionnaireCtrl.searchQuestionnaireById(illustration.QuestionnaireId);
if(!questionnaire)
{
if(illustrationDatas.url)
toolFile.deleteFile(configIllustrations.dirIllustrations, illustrationDatas.url);
throw { message: txt.needQuestionnaireForIllustration };
}
else if(req.connectedUser.User.status==="creator" && req.connectedUser.User.id!==questionnaire.Questionnaire.CreatorId)
{
if(illustrationDatas.url)
toolFile.deleteFile(configIllustrations.dirIllustrations, illustrationDatas.url);
res.status(401).json({ errors: txtGeneral.notAllowed });
}
else
{
if(!tool.isEmpty(req.body.fileError))
res.status(400).json({ errors: [req.body.fileError] });
else
{
const illustrationDatas = await checkHasFile(req);
// Lors d'une mise à jour, un nouveau fichier n'a pas forcément été envoyé ou peut avoir été bloqué par multer
// Mais si c'est le cas, on supprime l'ancien fichier :
if(illustrationDatas.url)
{
toolFile.deleteFile(configIllustrations.dirIllustrations, illustration.url);
toolFile.deleteFile(configIllustrations.dirIllustrations+"/min", illustration.url);
}
await db["Illustration"].update({ ...illustrationDatas }, { where: { id : req.params.id } , fields: ["url", "alt", "title", "caption"], limit:1 });
const questionnaireDatas=await questionnaireCtrl.creaQuestionnaireJson(illustrationDatas.QuestionnaireId);// me permet de retourner en réponse les infos actualisées pour les afficher
res.status(200).json({ message: txt.updatedOkMessage, questionnaire: questionnaireDatas });
}
}
}
next();
}
catch(e)
{
const returnAPI=toolError.returnSequelize(e);
if(returnAPI.messages)
{
res.status(returnAPI.status).json({ errors : returnAPI.messages });
next();
}
else
next(e);
}
}
exports.delete = async (req, res, next) =>
{
try
{
const db = require("../models/index");
const illustration=await searchIllustrationById(req.params.id);
if(!illustration)
throw { message: txt.notFound+req.params.id };
else
{
const questionnaire=await questionnaireCtrl.searchQuestionnaireById(illustration.QuestionnaireId);
if(!questionnaire)
throw { message: txt.needQuestionnaireForIllustration };
else if(req.connectedUser.User.status==="creator" && req.connectedUser.User.id!==questionnaire.Questionnaire.CreatorId)
res.status(401).json({ errors: txtGeneral.notAllowed });
else
{
const delIllus=await deleteIllustrationById(req.params.id);
if(delIllus)
{
const questionnaireDatas=await questionnaireCtrl.creaQuestionnaireJson(illustration.QuestionnaireId);// me permet de retourner en réponse les infos actualisées pour les afficher
res.status(200).json({ message: txt.deletedOkMessage, questionnaire: questionnaireDatas });
}
else
res.status(400).json({ errors: [txtGeneral.serverError] });
}
}
next();
}
catch(e)
{
next(e);
}
}
exports.getOneIllustrationById = async (req, res, next) =>
{
try
{
const illustration=await searchIllustrationById(req.params.id);
if(illustration)
res.status(200).json(illustration);
else
res.status(404).json(null);
}
catch(e)
{
next(e);
}
}
// cron de nettoyage des fichiers illustrations n'existant plus dans la bd
exports.deleteOldFiles= async (req, res, next) =>
{
try
{
const db = require("../models/index");
const illustrations=await db["Illustration"].findAll({ attributes: ["url"] });
let saveFiles=[];
for(let i in illustrations)
saveFiles.push(illustrations[i].url);
await toolFile.deleteFilesInDirectory(configIllustrations.dirIllustrations, saveFiles);
await toolFile.deleteFilesInDirectory(configIllustrations.dirIllustrations+"/min", saveFiles);
// + le répertoire temporaire où rien ne devrait traîner :
const fileExpiration=new Date().getTime()-1000;
await toolFile.deleteOldFilesInDirectory(configIllustrations.dirIllustrationsTmp, fileExpiration);
res.status(200).json(deleteFiles);
next();
}
catch(e)
{
next(e);
}
}
// FONCTIONS UTILITAIRES
// Gère le redimensionnement de l'image si un fichier est envoyé.
// c'est multer qui vérifie dans le middleware précédent que l'image a le bon format, puis lui donne un nom (filename) si c'est ok
const checkHasFile = async (req) =>
{
if(req.file)
{ // à revoir ? : là l'image est aggrandie si + petite que demandé
await sharp(req.file.path).resize(config.illustrationsWidthMaxInPx).toFile(configIllustrations.dirIllustrations+"/"+req.file.filename);
await sharp(req.file.path).resize(config.illustrationsMiniaturesWidthMaxInPx).toFile(configIllustrations.dirIllustrations+"/min/"+req.file.filename);
await toolFile.deleteFile(configIllustrations.dirIllustrationsTmp, req.file.filename);
}
// La gestion du téléchargement du fichier de l'illustration fait que les données sont envoyées sous forme de chaîne de caractères (form-data), qu'il faut transformer en json
const datas=req.file ? { ...req.body, url: req.file.filename } : { ...req.body };
return datas;
}
const searchIllustrationById = async (id) =>
{
const db = require("../models/index");
const illustration=await db["Illustration"].findByPk(id);
if(illustration)
return illustration;
else
return false;
}
const deleteIllustrationById = async (id) =>
{
const db = require("../models/index");
const illustration=await searchIllustrationById(id);
if(!illustration)
throw { message: txt.notFound+id };
else
{
const nb=await db["Illustration"].destroy( { where: { id : id }, limit:1 });
if(nb===1)
{
toolFile.deleteFile(configIllustrations.dirIllustrations, illustration.url);
toolFile.deleteFile(configIllustrations.dirIllustrations+"/min", illustration.url);
questionnaireCtrl.creaQuestionnaireJson(illustration.QuestionnaireId);
}
return true;
}
}
exports.deleteIllustrationById = deleteIllustrationById;