diff --git a/api/app.js b/api/app.js index 6ab858f..5b78647 100644 --- a/api/app.js +++ b/api/app.js @@ -37,12 +37,12 @@ app.use((error, _req, res, _next) => { }); /* Database Relations */ -const Functions = require('./models/functions'); -const Categories = require('./models/categories'); -const Users = require('./models/users'); -const Favorites = require('./models/favorites'); -const Comments = require('./models/comments'); -const Quotes = require('./models/quotes'); +const Functions = require('./models/functions'); +const Categories = require('./models/categories'); +const Users = require('./models/users'); +const Favorites = require('./models/favorites'); +const Comments = require('./models/comments'); +const Quotes = require('./models/quotes'); // A function has a category Categories.hasOne(Functions, { constraints: true, onDelete: 'CASCADE'}); diff --git a/api/assets/functions/functionObject.js b/api/assets/functions/functionObject.js index ba8ebe6..db4416c 100644 --- a/api/assets/functions/functionObject.js +++ b/api/assets/functions/functionObject.js @@ -9,6 +9,7 @@ const calculateAgeOutput = require('./main/calculateAge'); const heapAlgorithmOutput = require('./main/heapAlgorithm'); const convertEncodingOutput = require('./main/convertEncoding'); const randomQuote = require('./main/randomQuote'); +const linkShortener = require('./main/linkShortener'); const functionObject = { randomNumber : randomNumberOutput, @@ -22,6 +23,7 @@ const functionObject = { heapAlgorithm : heapAlgorithmOutput, convertEncoding : convertEncodingOutput, randomQuote : randomQuote, + linkShortener : linkShortener, }; // Choisi la fonction à exécuter diff --git a/api/assets/functions/main/linkShortener.js b/api/assets/functions/main/linkShortener.js new file mode 100644 index 0000000..8bdc058 --- /dev/null +++ b/api/assets/functions/main/linkShortener.js @@ -0,0 +1,52 @@ +const validator = require('validator'); +const errorHandling = require('../../utils/errorHandling'); +const { requiredFields, serverError } = require('../../config/errors'); +const Short_links = require('../../../models/short_links'); + +module.exports = linkShortener = async ({ res, next }, argsObject) => { + let { url, shortcutName } = argsObject; + + // S'il n'y a pas les champs obligatoire + if (!(url && shortcutName)) { + return errorHandling(next, requiredFields); + } + + // Si ce n'est pas une url + if (!validator.isURL(url)) { + return errorHandling(next, { message: "Veuillez entré une URL valide.", statusCode: 400 }); + } + + // Si ce n'est pas de type slug + if (!validator.isSlug(shortcutName)) { + return errorHandling(next, { message: "Le nom de votre raccourci doit être de type slug (ne pas contenir d'espaces, ni de caractères spéciaux).", statusCode: 400 }); + } + + // Sanitize shortcutName + shortcutName = validator.escape(shortcutName); + shortcutName = validator.trim(shortcutName); + shortcutName = validator.blacklist(shortcutName, ' '); + + try { + // Si l'url a déjà été raccourcie + const urlInDatabase = await Short_links.findOne({ where: { url } }); + if (urlInDatabase) { + const urlShort = `https://short-links.divlo.fr/?q=${urlInDatabase.shortcut}`; + return errorHandling(next, { message: `L'url a déjà été raccourcie...

${urlShort}`, statusCode: 400 }); + } + + // Si le nom du raccourci existe déjà + const shortcutInDatabase = await Short_links.findOne({ where: { shortcut: shortcutName } }); + if (shortcutInDatabase) { + const urlShort = `https://short-links.divlo.fr/?q=${shortcutInDatabase.shortcut}`; + return errorHandling(next, { message: `Le nom du raccourci a déjà été utilisé...

${urlShort}`, statusCode: 400 }); + } + + // Ajout du lien raccourci + const result = await Short_links.create({ url, shortcut: shortcutName }); + const shortcutLinkResult = `https://short-links.divlo.fr/?q=${result.shortcut}`; + return res.status(200).json({ resultHTML: `URL Raccourcie :

${shortcutLinkResult}`, result: shortcutLinkResult }); + } catch { + console.log(error); + return errorHandling(next, serverError); + } +} \ No newline at end of file diff --git a/api/models/short_links.js b/api/models/short_links.js new file mode 100644 index 0000000..1ce431c --- /dev/null +++ b/api/models/short_links.js @@ -0,0 +1,19 @@ +const Sequelize = require('sequelize'); +const sequelize = require('../assets/utils/database'); + +module.exports = sequelize.define('short_link', { + id: { + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true + }, + url: { + type: Sequelize.TEXT, + allowNull: false, + }, + shortcut: { + type: Sequelize.TEXT, + allowNull: false, + } +}); \ No newline at end of file diff --git a/api/package-lock.json b/api/package-lock.json index 9e1a4a7..e6dbf9f 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -1545,6 +1545,11 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" } } }, @@ -1798,9 +1803,9 @@ "integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==" }, "validator": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", - "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.0.0.tgz", + "integrity": "sha512-anYx5fURbgF04lQV18nEQWZ/3wHGnxiKdG4aL8J+jEDsm98n/sU/bey+tYk6tnGJzm7ioh5FoqrAiQ6m03IgaA==" }, "vary": { "version": "1.1.2", diff --git a/api/package.json b/api/package.json index 52cedb5..3e81f8e 100644 --- a/api/package.json +++ b/api/package.json @@ -25,7 +25,8 @@ "nodemailer": "^6.4.6", "sequelize": "^5.21.5", "smart-request-balancer": "^2.1.1", - "uuid": "^7.0.2" + "uuid": "^7.0.2", + "validator": "^13.0.0" }, "devDependencies": { "dotenv": "^8.2.0",