Compare commits
No commits in common. "master" and "v2.0" have entirely different histories.
131
.github/CODE_OF_CONDUCT.md
vendored
@ -1,131 +0,0 @@
|
|||||||
# Code de conduite _Contributor Covenant_
|
|
||||||
|
|
||||||
## Notre engagement
|
|
||||||
|
|
||||||
En tant que membres, contributeur•trice•s et dirigeant•e•s, nous nous
|
|
||||||
engageons à faire de la participation à notre communauté
|
|
||||||
une expérience sans harcèlement, quel que soit l'âge,
|
|
||||||
la taille corporelle, le handicap visible ou invisible, l'appartenance ethnique,
|
|
||||||
les caractéristiques sexuelles, l'identité et l'expression de genre,
|
|
||||||
le niveau d'expérience, l'éducation, le statut socio-économique,
|
|
||||||
la nationalité, l'apparence personnelle, la race, la religion,
|
|
||||||
ou l'identité et l'orientation sexuelle.
|
|
||||||
|
|
||||||
Nous nous engageons à agir et interagir de manière à contribuer à une communauté
|
|
||||||
ouverte, accueillante, diversifiée, inclusive et saine.
|
|
||||||
|
|
||||||
## Nos critères
|
|
||||||
|
|
||||||
Exemples de comportements qui contribuent à créer un environnement positif :
|
|
||||||
|
|
||||||
- Faire preuve d'empathie et de bienveillance envers les autres
|
|
||||||
- Être respectueux des opinions, points de vue et expériences divergents
|
|
||||||
- Donner et recevoir avec grâce les critiques constructives
|
|
||||||
- Assumer ses responsabilités et s'excuser auprès des personnes affectées par nos erreurs et apprendre de ces expériences
|
|
||||||
- Se concentrer sur ce qui est le meilleur non pas uniquement pour nous en tant qu'individu, mais aussi pour l'ensemble de la communauté
|
|
||||||
|
|
||||||
Exemples de comportements inacceptables :
|
|
||||||
|
|
||||||
- L'utilisation de langage ou d'images sexualisés et d'attentions ou d'avances sexuelles de toute nature
|
|
||||||
- Le _trolling_, les commentaires insultants ou désobligeants et les attaques
|
|
||||||
personnelles ou d'ordre politique
|
|
||||||
- Le harcèlement en public ou en privé
|
|
||||||
- La publication d'informations privées d'autrui, telle qu'une
|
|
||||||
adresse postale ou une adresse électronique, sans leur autorisation explicite
|
|
||||||
- Toute autre conduite qui pourrait raisonnablement être considérée comme inappropriée
|
|
||||||
dans un cadre professionnel
|
|
||||||
|
|
||||||
## Responsabilités d'application
|
|
||||||
|
|
||||||
Les dirigeant•e•s de la communauté sont chargé•e•s de clarifier et de faire respecter nos normes de
|
|
||||||
comportements acceptables et prendront des mesures correctives appropriées et équitables en
|
|
||||||
réponse à tout comportement qu'ils ou elles jugent inapproprié, menaçant, offensant ou nuisible.
|
|
||||||
|
|
||||||
Les dirigeant•e•s de la communauté ont le droit et la responsabilité de supprimer, modifier ou rejeter
|
|
||||||
les commentaires, les contributions, le code, les modifications de wikis, les rapports d'incidents ou de bogues et autres contributions qui
|
|
||||||
ne sont pas alignés sur ce code de conduite, et communiqueront les raisons des décisions de modération
|
|
||||||
le cas échéant.
|
|
||||||
|
|
||||||
## Portée d'application
|
|
||||||
|
|
||||||
Ce code de conduite s'applique à la fois au sein des espaces du projet ainsi que
|
|
||||||
dans les espaces publics lorsqu'un individu représente officiellement le projet ou sa
|
|
||||||
communauté. Font parties des exemples de représentation d'un projet ou d'une
|
|
||||||
communauté l'utilisation d'une adresse électronique officielle, la publication sur
|
|
||||||
les réseaux sociaux à l'aide d'un compte officiel ou le fait d'agir en tant que représentant•e désigné•e
|
|
||||||
lors d'un événement en ligne ou hors-ligne.
|
|
||||||
|
|
||||||
## Application
|
|
||||||
|
|
||||||
Les cas de comportements abusifs, harcelants ou tout autre comportement
|
|
||||||
inacceptables peuvent être signalés aux dirigeant•e•s de la communauté responsables de l'application du code de conduite à
|
|
||||||
contact@divlo.fr.
|
|
||||||
Toutes les plaintes seront examinées et feront l'objet d'une enquête rapide et équitable.
|
|
||||||
|
|
||||||
Tou•te•s les dirigeant•e•s de la communauté sont tenu•e•s de respecter la vie privée et la sécurité des
|
|
||||||
personnes ayant signalé un incident.
|
|
||||||
|
|
||||||
## Directives d'application
|
|
||||||
|
|
||||||
Les dirigeant•e•s de communauté suivront ces directives d'application sur l'impact communautaire afin de déterminer
|
|
||||||
les conséquences de toute action qu'ils jugent contraire au présent code de conduite :
|
|
||||||
|
|
||||||
### 1. Correction
|
|
||||||
|
|
||||||
**Impact communautaire** : utilisation d'un langage inapproprié ou tout autre comportement jugé
|
|
||||||
non professionnel ou indésirable dans la communauté.
|
|
||||||
|
|
||||||
**Conséquence** : un avertissement écrit et privé de la part des dirigeant•e•s de la communauté, clarifiant
|
|
||||||
la nature du non-respect et expliquant pourquoi
|
|
||||||
le comportement était inapproprié. Des excuses publiques peuvent être demandées.
|
|
||||||
|
|
||||||
### 2. Avertissement
|
|
||||||
|
|
||||||
**Impact communautaire** : un non-respect par un seul incident ou une série d'actions.
|
|
||||||
|
|
||||||
**Conséquence** : un avertissement avec des conséquences dû à la poursuite du comportement.
|
|
||||||
Aucune interaction avec les personnes concernées, y compris l'interaction non sollicitée avec
|
|
||||||
celles et ceux qui sont chargé•e•s de l'application de ce code de conduite, pendant une période déterminée.
|
|
||||||
Cela comprend le fait d'éviter les interactions dans les espaces communautaires ainsi que sur les canaux externes
|
|
||||||
comme les médias sociaux. Le non-respect de ces conditions peut entraîner
|
|
||||||
un bannissement temporaire ou permanent.
|
|
||||||
|
|
||||||
### 3. Bannissement temporaire
|
|
||||||
|
|
||||||
**Impact communautaire** : un non-respect grave des normes communautaires, notamment
|
|
||||||
un comportement inapproprié soutenu.
|
|
||||||
|
|
||||||
**Conséquence** : un bannissement temporaire de toutes formes d'interactions ou de
|
|
||||||
communications avec la communauté pendant une période déterminée. Aucune interaction publique ou
|
|
||||||
privée avec les personnes concernées, y compris les interactions non sollicitées
|
|
||||||
avec celles et ceux qui appliquent ce code de conduite, n'est autorisée pendant cette période.
|
|
||||||
Le non-respect de ces conditions peut entraîner un bannissement permanent.
|
|
||||||
|
|
||||||
### 4. Bannissement permanent
|
|
||||||
|
|
||||||
**Impact communautaire** : démontrer un schéma récurrent de non-respect des normes de la
|
|
||||||
communauté y compris un comportement inapproprié soutenu, le harcèlement d'un individu
|
|
||||||
ainsi que l'agression ou le dénigrement de catégories d'individus.
|
|
||||||
|
|
||||||
**Conséquence** : un bannissement permanent de toutes formes d'interactions publiques au sein de
|
|
||||||
la communauté.
|
|
||||||
|
|
||||||
## Attributions
|
|
||||||
|
|
||||||
Ce code de conduite est adapté du
|
|
||||||
[Contributor Covenant](https://www.contributor-covenant.org), version 2.0,
|
|
||||||
disponible à
|
|
||||||
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
|
|
||||||
|
|
||||||
Les Directives d'application ont été inspirées par le
|
|
||||||
[Code of conduct enforcement ladder][mozilla coc] de Mozilla.
|
|
||||||
|
|
||||||
Pour obtenir des réponses aux questions courantes sur ce code de conduite, consultez la FAQ à
|
|
||||||
[https://www.contributor-covenant.org/faq][faq]. Les traductions sont disponibles
|
|
||||||
sur [https://www.contributor-covenant.org/translations][translations].
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
|
||||||
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
|
|
||||||
[mozilla coc]: https://github.com/mozilla/diversity
|
|
||||||
[faq]: https://www.contributor-covenant.org/faq
|
|
||||||
[translations]: https://www.contributor-covenant.org/translations
|
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
14
.github/ISSUE_TEMPLATE/BUG.md
vendored
@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
name: '🐛 Rapport de bug'
|
|
||||||
about: 'Signalez un problème inattendu ou un comportement involontaire.'
|
|
||||||
labels: 'bug'
|
|
||||||
---
|
|
||||||
|
|
||||||
## Étapes à suivre pour reproduire le bug
|
|
||||||
|
|
||||||
1. Étape 1
|
|
||||||
2. Étape 2
|
|
||||||
|
|
||||||
## Comportement actuel
|
|
||||||
|
|
||||||
## Comportement attendu
|
|
7
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
name: '✨ Ajout d'une fonctionnalité'
|
|
||||||
about: 'Suggérer une nouvelle fonctionnalité.'
|
|
||||||
labels: 'feature request'
|
|
||||||
---
|
|
||||||
|
|
||||||
### Description
|
|
7
.github/ISSUE_TEMPLATE/QUESTION.md
vendored
@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
name: '🙋 Question'
|
|
||||||
about: 'Des informations complémentaires sont demandées.'
|
|
||||||
labels: 'question'
|
|
||||||
---
|
|
||||||
|
|
||||||
### Question
|
|
2
.github/backup.sql
vendored
18
.github/workflows/commitlint.yml
vendored
@ -1,18 +0,0 @@
|
|||||||
# For more information see: https://github.com/marketplace/actions/commit-linter
|
|
||||||
|
|
||||||
name: 'Lint Commit Messages'
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master]
|
|
||||||
pull_request:
|
|
||||||
branches: [master]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
commitlint:
|
|
||||||
runs-on: 'ubuntu-latest'
|
|
||||||
steps:
|
|
||||||
- uses: 'actions/checkout@v2'
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- uses: 'wagoid/commitlint-github-action@v2'
|
|
61
.github/workflows/nodejs.yml
vendored
@ -1,61 +0,0 @@
|
|||||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
|
||||||
|
|
||||||
name: 'Node.js CI'
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master]
|
|
||||||
pull_request:
|
|
||||||
branches: [master]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci_website:
|
|
||||||
runs-on: 'ubuntu-latest'
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: 'website'
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
node-version: [14.x]
|
|
||||||
steps:
|
|
||||||
- uses: 'actions/checkout@v2'
|
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: 'actions/setup-node@v2.1.2'
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
|
|
||||||
- name: 'Cache dependencies'
|
|
||||||
uses: 'actions/cache@v2'
|
|
||||||
with:
|
|
||||||
path: '**/node_modules'
|
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
|
||||||
|
|
||||||
- run: 'npm install'
|
|
||||||
- run: 'npm run lint'
|
|
||||||
- run: 'npm run build'
|
|
||||||
|
|
||||||
ci_api:
|
|
||||||
runs-on: 'ubuntu-latest'
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
working-directory: 'api'
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
node-version: [14.x]
|
|
||||||
steps:
|
|
||||||
- uses: 'actions/checkout@v2'
|
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: 'actions/setup-node@v2.1.2'
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
|
|
||||||
- name: 'Cache dependencies'
|
|
||||||
uses: 'actions/cache@v2'
|
|
||||||
with:
|
|
||||||
path: '**/node_modules'
|
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
|
||||||
|
|
||||||
- run: 'npm install'
|
|
||||||
- run: 'npm run lint'
|
|
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.github/backup
|
23
LICENSE
@ -1,21 +1,8 @@
|
|||||||
MIT License
|
The MIT License (MIT)
|
||||||
|
Copyright © 2020 Divlo
|
||||||
|
|
||||||
Copyright (c) Divlo
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
56
README.md
@ -1,21 +1,17 @@
|
|||||||
<h1 align="center"><a href="https://function.divlo.fr/">FunctionProject</a></h1>
|
<h1 align="center"><a href="https://function.divlo.fr/">FunctionProject</a></h1>
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<strong>⚠️ Le projet n'est plus maintenu.</strong>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<strong>Apprenez la programmation grâce à l'apprentissage par projet alias fonction.</strong>
|
<strong>Apprenez la programmation grâce à l'apprentissage par projet alias fonction.</strong>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/Divlo/FunctionProject/actions?query=workflow%3A%22Node.js+CI%22"><img src="https://github.com/Divlo/FunctionProject/workflows/Node.js%20CI/badge.svg" alt="Node.js CI" /></a>
|
|
||||||
<a href="https://standardjs.com"><img alt="JavaScript Style Guide" src="https://img.shields.io/badge/code_style-standard-brightgreen.svg"/></a>
|
|
||||||
<a href="./LICENSE"><img src="https://img.shields.io/badge/licence-MIT-blue.svg" alt="Licence MIT"/></a>
|
<a href="./LICENSE"><img src="https://img.shields.io/badge/licence-MIT-blue.svg" alt="Licence MIT"/></a>
|
||||||
<a href="https://conventionalcommits.org"><img src="https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg" alt="Conventional Commits" /></a>
|
<img src="https://img.shields.io/github/repo-size/Divlo/FunctionProject" alt="Repo Size">
|
||||||
<a href="./.github/CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg" alt="Contributor Covenant" /></a>
|
<a href="https://github.com/Divlo/FunctionProject/commits/master"><img src="https://img.shields.io/github/commit-activity/m/Divlo/FunctionProject" alt="Commit Activity"></a>
|
||||||
|
<a href="https://github.com/Divlo/FunctionProject/graphs/contributors"><img src="https://img.shields.io/github/contributors/Divlo/FunctionProject" alt="Contributors"></a>
|
||||||
|
<img src="https://img.shields.io/github/stars/Divlo/FunctionProject?style=social" alt="Stars">
|
||||||
<br/> <br/>
|
<br/> <br/>
|
||||||
<a href="https://function.divlo.fr/"><img src="https://raw.githubusercontent.com/Divlo/FunctionProject/master/.github/images/FunctionProject.png" alt="FunctionProject" /></a>
|
<a href="https://function.divlo.fr/"><img src="https://raw.githubusercontent.com/Divlo/FunctionProject/master/.github/FunctionProject.png" alt="FunctionProject" /></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## ⚙️ À propos
|
## ⚙️ À propos
|
||||||
@ -28,13 +24,13 @@ Si vous aimez le projet, vous pouvez aider à **le faire connaître** en utilisa
|
|||||||
|
|
||||||
Les dernières versions publiées : [https://github.com/Divlo/FunctionProject/releases](https://github.com/Divlo/FunctionProject/releases)
|
Les dernières versions publiées : [https://github.com/Divlo/FunctionProject/releases](https://github.com/Divlo/FunctionProject/releases)
|
||||||
|
|
||||||
Le projet est disponible sur [function.divlo.fr](https://function.divlo.fr/) (actuellement en version 2.3).
|
Le projet est disponible sur [function.divlo.fr](https://function.divlo.fr/) (actuellement en version 2.0).
|
||||||
|
|
||||||
## 🚀 Open Source
|
## 🚀 Open Source
|
||||||
|
|
||||||
Le partage est essentiel afin de progresser, l'**Open Source** permet l'entraide et le **partage de connaissance** entre développeurs.
|
Le partage est essentiel afin de progresser, l'**Open Source** permet l'entraide et le **partage de connaissance** entre développeurs.
|
||||||
|
|
||||||
Si vous voulez **contribuer**, avant toute chose écrivez une **"[issue](https://github.com/Divlo/FunctionProject/issues)" sur GitHub** à propos des changements que vous voulez apporter et on pourra en **discuter avec grand plaisir**. 😉
|
Si vous voulez **contribuer**, avant toute chose écrivait une **"[issue](https://github.com/Divlo/FunctionProject/issues)" sur GitHub** à propos des changements que vous voulez apporter et on pourra en **discuter avec grand plaisir**. 😉
|
||||||
|
|
||||||
## 🌐 Installation
|
## 🌐 Installation
|
||||||
|
|
||||||
@ -42,13 +38,12 @@ Si vous voulez **contribuer**, avant toute chose écrivez une **"[issue](https:/
|
|||||||
|
|
||||||
Si vous voulez avoir les données des catégories et des fonctions, vous pouvez d'abord lancer l'API pour que Sequelize crée les tables SQl et ensuite exécuter le fichier SQL [backup.sql](./.github/backup.sql).
|
Si vous voulez avoir les données des catégories et des fonctions, vous pouvez d'abord lancer l'API pour que Sequelize crée les tables SQl et ensuite exécuter le fichier SQL [backup.sql](./.github/backup.sql).
|
||||||
|
|
||||||
### Prérequis
|
### Prérequis :
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org/) >= 14
|
- NodeJS (et npm) → version récente
|
||||||
- [npm](https://www.npmjs.com/) >= 7
|
- Base de donnée MySQL → J'utilise Wamp ce qui me permet d'avoir phpmyadmin.
|
||||||
- [MySQL](https://www.mysql.com/) >= 8
|
|
||||||
|
|
||||||
### Commandes (à suivre dans l'ordre)
|
### Commandes (à suivre dans l'ordre) :
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Cloner le projet
|
# Cloner le projet
|
||||||
@ -64,44 +59,23 @@ cd ../website
|
|||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
Vous devrez ensuite configurer les variables d'environnements en créant un fichier `.env` à la racine du dossier `/api`, `/website` et `s.divlo.fr` pour prendre exemple du fichier `.env.example` avec votre configuration.
|
Vous devrez ensuite configurer l'API en créant un fichier `.env` à la racine du dossier `/api` et prendre exemple du fichier `.env.example` avec votre configuration.
|
||||||
|
|
||||||
### Lancer l'environnement de développement
|
### Lancer l'environnement de développement :
|
||||||
|
|
||||||
#### Avec [docker](https://www.docker.com/)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# Setup and run all the services for you
|
|
||||||
docker-compose up --build
|
|
||||||
```
|
|
||||||
|
|
||||||
**Services started :**
|
|
||||||
|
|
||||||
- api : `http://localhost:8080`
|
|
||||||
- s.divlo.fr : `http://localhost:7000`
|
|
||||||
- website : `http://localhost:3000`
|
|
||||||
- [phpmyadmin](https://www.phpmyadmin.net/) : `http://localhost:8000`
|
|
||||||
- [MailDev](https://maildev.github.io/maildev/) : `http://localhost:1080`
|
|
||||||
- [MySQL database](https://www.mysql.com/) (with PORT 3006)
|
|
||||||
|
|
||||||
#### Sans docker
|
|
||||||
|
|
||||||
Dans deux terminals séparés :
|
Dans deux terminals séparés :
|
||||||
|
|
||||||
- Lancer le front-end en allant dans `/website`
|
- Lancer le front-end en allant dans `/website`
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm run dev # front-end lancé sur http://localhost:3000
|
npm run dev # front-end lancé sur http://localhost:3000
|
||||||
```
|
```
|
||||||
|
|
||||||
- Lancer l'api en allant dans `/api`
|
- Lancer l'api en allant dans `/api`
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm run dev # API lancé sur http://localhost:8080
|
npm run dev # API lancé sur http://localhost:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
Enjoy! 😃
|
Enjoy! 😃
|
||||||
|
|
||||||
## 📄 License
|
## 📄 Licence
|
||||||
|
|
||||||
[MIT](./LICENSE)
|
Ce projet est sous licence MIT - voir le fichier [LICENSE](./LICENSE) pour plus de détails.
|
@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
build
|
|
@ -1,15 +1,11 @@
|
|||||||
COMPOSE_PROJECT_NAME="function.divlo.fr-api"
|
|
||||||
HOST = "http://localhost:8080"
|
HOST = "http://localhost:8080"
|
||||||
FRONT_END_HOST = "http://localhost:3000"
|
FRONT_END_HOST = "http://localhost:3000"
|
||||||
OpenWeatherMap_API_KEY = ""
|
OpenWeatherMap_API_KEY = ""
|
||||||
Scraper_API_KEY=""
|
DB_HOST = ""
|
||||||
DATABASE_HOST="functionproject-database"
|
DB_NAME = ""
|
||||||
DATABASE_NAME="functionproject"
|
DB_USER = ""
|
||||||
DATABASE_USER="root"
|
DB_PASS = ""
|
||||||
DATABASE_PASSWORD="password"
|
|
||||||
DATABASE_PORT=3306
|
|
||||||
JWT_SECRET = ""
|
JWT_SECRET = ""
|
||||||
EMAIL_HOST="functionproject-maildev"
|
EMAIL_HOST = ""
|
||||||
EMAIL_USER="no-reply@functionproject.fr"
|
EMAIL_USER = ""
|
||||||
EMAIL_PASSWORD="password"
|
EMAIL_PASSWORD = ""
|
||||||
EMAIL_PORT=25
|
|
9
api/.gitignore
vendored
@ -11,18 +11,15 @@
|
|||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
|
|
||||||
# envs
|
# misc
|
||||||
|
.DS_Store
|
||||||
.env
|
.env
|
||||||
.env.local
|
.env.local
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
.env.production
|
|
||||||
|
|
||||||
# misc
|
|
||||||
.DS_Store
|
|
||||||
/temp
|
/temp
|
||||||
/assets/images/users
|
/assets/images/
|
||||||
|
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
FROM node:14.16.1
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY ./package*.json ./
|
|
||||||
RUN npm install
|
|
||||||
COPY ./ ./
|
|
||||||
|
|
||||||
# docker-compose-wait
|
|
||||||
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.7.3/wait /wait
|
|
||||||
RUN chmod +x /wait
|
|
||||||
|
|
||||||
CMD /wait && npm run dev
|
|
141
api/app.js
@ -1,110 +1,83 @@
|
|||||||
/* Modules */
|
/* Modules */
|
||||||
require('dotenv').config()
|
require('dotenv').config();
|
||||||
const path = require('path')
|
const path = require('path');
|
||||||
const express = require('express')
|
const express = require('express');
|
||||||
const helmet = require('helmet')
|
const helmet = require('helmet');
|
||||||
const cors = require('cors')
|
const cors = require('cors');
|
||||||
const morgan = require('morgan')
|
const morgan = require('morgan');
|
||||||
const { redirectToHTTPS } = require('express-http-to-https')
|
const redirectToHTTPS = require('express-http-to-https').redirectToHTTPS;
|
||||||
const rateLimit = require('express-rate-limit')
|
|
||||||
|
|
||||||
/* Files Imports & Variables */
|
/* Files Imports & Variables */
|
||||||
const sequelize = require('./assets/utils/database')
|
const sequelize = require('./assets/utils/database');
|
||||||
const { PORT } = require('./assets/config/config')
|
const { PORT } = require('./assets/config/config');
|
||||||
const errorHandling = require('./assets/utils/errorHandling')
|
const errorHandling = require('./assets/utils/errorHandling');
|
||||||
const isAuth = require('./middlewares/isAuth')
|
const isAuth = require('./middlewares/isAuth');
|
||||||
const isAdmin = require('./middlewares/isAdmin')
|
const isAdmin = require('./middlewares/isAdmin');
|
||||||
const app = express()
|
const app = express();
|
||||||
|
|
||||||
/* Middlewares */
|
/* Middlewares */
|
||||||
if (process.env.NODE_ENV === 'development') {
|
app.use(helmet());
|
||||||
app.use(morgan('dev'))
|
app.use(cors());
|
||||||
} else if (process.env.NODE_ENV === 'production') {
|
app.use(morgan('dev'));
|
||||||
app.use(redirectToHTTPS())
|
app.use(express.json());
|
||||||
const requestPerSecond = 2
|
app.use(redirectToHTTPS([/localhost:(\d{4})/]));
|
||||||
const seconds = 60
|
|
||||||
const windowMs = seconds * 1000
|
|
||||||
app.enable('trust proxy')
|
|
||||||
app.use(
|
|
||||||
rateLimit({
|
|
||||||
windowMs,
|
|
||||||
max: seconds * requestPerSecond,
|
|
||||||
handler: (_req, res) => {
|
|
||||||
return res.status(429).json({ message: 'Too many requests' })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
app.use(helmet())
|
|
||||||
app.use(cors())
|
|
||||||
app.use(express.json())
|
|
||||||
|
|
||||||
/* Routes */
|
/* Routes */
|
||||||
app.use('/images', express.static(path.join(__dirname, 'assets', 'images')))
|
app.use('/images', express.static(path.join(__dirname, "assets", "images")));
|
||||||
app.use('/functions', require('./routes/functions'))
|
app.use('/functions', require('./routes/functions'));
|
||||||
app.use('/categories', require('./routes/categories'))
|
app.use('/categories', require('./routes/categories'));
|
||||||
app.use('/users', require('./routes/users'))
|
app.use('/users', require('./routes/users'));
|
||||||
app.use('/admin', isAuth, isAdmin, require('./routes/admin'))
|
app.use('/admin', isAuth, isAdmin, require('./routes/admin'));
|
||||||
app.use('/favorites', require('./routes/favorites'))
|
app.use('/favorites', require('./routes/favorites'));
|
||||||
app.use('/comments', require('./routes/comments'))
|
app.use('/comments', require('./routes/comments'));
|
||||||
app.use('/quotes', require('./routes/quotes'))
|
app.use('/quotes', require('./routes/quotes'));
|
||||||
app.use('/tasks', require('./routes/tasks'))
|
app.use('/tasks', require('./routes/tasks'));
|
||||||
app.use('/links', require('./routes/links_shortener'))
|
|
||||||
|
|
||||||
/* Errors Handling */
|
/* Errors Handling */
|
||||||
app.use((_req, _res, next) =>
|
app.use((_req, _res, next) => errorHandling(next, { statusCode: 404, message: "La route n'existe pas!" })); // 404
|
||||||
errorHandling(next, { statusCode: 404, message: "La route n'existe pas!" })
|
|
||||||
)
|
|
||||||
app.use((error, _req, res, _next) => {
|
app.use((error, _req, res, _next) => {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
const { statusCode, message } = error
|
const { statusCode, message } = error;
|
||||||
return res.status(statusCode || 500).json({ message })
|
return res.status(statusCode || 500).json({ message });
|
||||||
})
|
});
|
||||||
|
|
||||||
/* Database Relations */
|
/* Database Relations */
|
||||||
const Functions = require('./models/functions')
|
const Functions = require('./models/functions');
|
||||||
const Categories = require('./models/categories')
|
const Categories = require('./models/categories');
|
||||||
const Users = require('./models/users')
|
const Users = require('./models/users');
|
||||||
const Favorites = require('./models/favorites')
|
const Favorites = require('./models/favorites');
|
||||||
const Comments = require('./models/comments')
|
const Comments = require('./models/comments');
|
||||||
const Quotes = require('./models/quotes')
|
const Quotes = require('./models/quotes');
|
||||||
const Tasks = require('./models/tasks')
|
const Tasks = require('./models/tasks');
|
||||||
const ShortLinks = require('./models/short_links')
|
|
||||||
|
|
||||||
// A function has a category
|
// A function has a category
|
||||||
Categories.hasOne(Functions, { constraints: true, onDelete: 'CASCADE' })
|
Categories.hasOne(Functions, { constraints: true, onDelete: 'CASCADE'});
|
||||||
Functions.belongsTo(Categories)
|
Functions.belongsTo(Categories);
|
||||||
|
|
||||||
// Users can have favorites functions
|
// Users can have favorites functions
|
||||||
Users.hasMany(Favorites)
|
Users.hasMany(Favorites);
|
||||||
Favorites.belongsTo(Users, { constraints: false })
|
Favorites.belongsTo(Users, { constraints: false });
|
||||||
Functions.hasMany(Favorites)
|
Functions.hasMany(Favorites);
|
||||||
Favorites.belongsTo(Functions, { constraints: false })
|
Favorites.belongsTo(Functions, { constraints: false });
|
||||||
|
|
||||||
// Users can post comments on functions
|
// Users can post comments on functions
|
||||||
Users.hasMany(Comments)
|
Users.hasMany(Comments);
|
||||||
Comments.belongsTo(Users, { constraints: false })
|
Comments.belongsTo(Users, { constraints: false });
|
||||||
Functions.hasMany(Comments)
|
Functions.hasMany(Comments);
|
||||||
Comments.belongsTo(Functions, { constraints: false })
|
Comments.belongsTo(Functions, { constraints: false });
|
||||||
|
|
||||||
// Users can suggest new quotes
|
// Users can suggest new quotes
|
||||||
Users.hasMany(Quotes)
|
Users.hasMany(Quotes);
|
||||||
Quotes.belongsTo(Users, { constraints: false })
|
Quotes.belongsTo(Users, { constraints: false });
|
||||||
|
|
||||||
// Users can have tasks
|
// Users can have tasks
|
||||||
Users.hasMany(Tasks)
|
Users.hasMany(Tasks);
|
||||||
Tasks.belongsTo(Users, { constraints: false })
|
Tasks.belongsTo(Users, { constraints: false });
|
||||||
|
|
||||||
// Users can have links
|
|
||||||
Users.hasMany(ShortLinks)
|
|
||||||
ShortLinks.belongsTo(Users, { constraints: false })
|
|
||||||
|
|
||||||
/* Server */
|
/* Server */
|
||||||
sequelize
|
// sequelize.sync({ force: true })
|
||||||
.sync()
|
sequelize.sync()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
app.listen(PORT, () =>
|
app.listen(PORT, () => console.log('\x1b[36m%s\x1b[0m', `Started on port ${PORT}.`));
|
||||||
console.log('\x1b[36m%s\x1b[0m', `Started on port ${PORT}.`)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.catch(error => console.log(error))
|
.catch((error) => console.log(error));
|
@ -1,33 +1,25 @@
|
|||||||
const dotenv = require('dotenv')
|
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
const EMAIL_PORT = parseInt(process.env.EMAIL_PORT ?? '465', 10)
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
PORT: process.env.PORT || 8080,
|
PORT: process.env.PORT || 8080,
|
||||||
HOST: process.env.HOST,
|
HOST: process.env.HOST,
|
||||||
FRONT_END_HOST: process.env.FRONT_END_HOST,
|
FRONT_END_HOST: process.env.FRONT_END_HOST,
|
||||||
WEATHER_API_KEY: process.env.OpenWeatherMap_API_KEY,
|
WEATHER_API_KEY: process.env.OpenWeatherMap_API_KEY,
|
||||||
SCRAPER_API_KEY: process.env.Scraper_API_KEY,
|
|
||||||
DATABASE: {
|
DATABASE: {
|
||||||
host: process.env.DATABASE_HOST,
|
host: process.env.DB_HOST,
|
||||||
name: process.env.DATABASE_NAME,
|
name: process.env.DB_NAME,
|
||||||
user: process.env.DATABASE_USER,
|
user: process.env.DB_USER,
|
||||||
password: process.env.DATABASE_PASSWORD,
|
password: process.env.DB_PASS
|
||||||
port: parseInt(process.env.DATABASE_PORT ?? '3306', 10)
|
|
||||||
},
|
},
|
||||||
JWT_SECRET: process.env.JWT_SECRET,
|
JWT_SECRET: process.env.JWT_SECRET,
|
||||||
EMAIL_INFO: {
|
EMAIL_INFO: {
|
||||||
host: process.env.EMAIL_HOST,
|
host: process.env.EMAIL_HOST,
|
||||||
port: EMAIL_PORT,
|
port: 465,
|
||||||
secure: EMAIL_PORT === 465,
|
secure: true, // true for 465, false for other ports
|
||||||
auth: {
|
auth: {
|
||||||
user: process.env.EMAIL_USER,
|
user: process.env.EMAIL_USER,
|
||||||
pass: process.env.EMAIL_PASSWORD
|
pass: process.env.EMAIL_PASSWORD
|
||||||
},
|
}
|
||||||
ignoreTLS: process.env.NODE_ENV !== 'production'
|
|
||||||
},
|
},
|
||||||
TOKEN_LIFE: '1 week'
|
TOKEN_LIFE: '1 week'
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = config
|
module.exports = config;
|
@ -26,24 +26,16 @@ exports.emailQuoteTemplate = (isValid, quote, frontendLink) => `
|
|||||||
<tr>
|
<tr>
|
||||||
<td align="left" valign="top" style="line-height:150%;font-family:Helvetica;font-size:14px;color:rgb(222, 222, 222);padding:30px;box-shadow: 0px 0px 6px 6px rgba(0, 0, 0, .25);border: 1px solid black;border-radius: 1rem;">
|
<td align="left" valign="top" style="line-height:150%;font-family:Helvetica;font-size:14px;color:rgb(222, 222, 222);padding:30px;box-shadow: 0px 0px 6px 6px rgba(0, 0, 0, .25);border: 1px solid black;border-radius: 1rem;">
|
||||||
<h2 style="font-size:22px;line-height:28px;margin:0 0 12px 0;">
|
<h2 style="font-size:22px;line-height:28px;margin:0 0 12px 0;">
|
||||||
La citation que vous avez proposée a été ${
|
La citation que vous avez proposée a été ${(isValid) ? "validée" : "supprimée"}.
|
||||||
isValid
|
|
||||||
? 'validée'
|
|
||||||
: 'supprimée'
|
|
||||||
}.
|
|
||||||
</h2>
|
</h2>
|
||||||
<p style="margin: 0 0 12px 0;">
|
<p style="margin: 0 0 12px 0;">
|
||||||
<a style="color: #ffd800;" href="${frontendLink}/functions/randomQuote">Lien vers la fonction randomQuote de FunctionProject.</a>
|
<a style="color: #ffd800;" href="${frontendLink}/functions/randomQuote">Lien vers la fonction randomQuote de FunctionProject.</a>
|
||||||
</p>
|
</p>
|
||||||
${
|
${(!isValid) ? `
|
||||||
!isValid
|
|
||||||
? `
|
|
||||||
<p style="margin: 0 0 12px 0;">
|
<p style="margin: 0 0 12px 0;">
|
||||||
Si votre citation a été supprimée et vous pensez que c'est une erreur, contactez-moi à cette adresse email : <a style="color: #ffd800;" href="mailto:contact@divlo.fr">contact@divlo.fr</a>.
|
Si votre citation a été supprimée et vous pensez que c'est une erreur, contactez-moi à cette adresse email : <a style="color: #ffd800;" href="mailto:contact@divlo.fr">contact@divlo.fr</a>.
|
||||||
</p>
|
</p>
|
||||||
`
|
` : ""}
|
||||||
: ''
|
|
||||||
}
|
|
||||||
<div>
|
<div>
|
||||||
<p style="padding:0 0 10px 0">
|
<p style="padding:0 0 10px 0">
|
||||||
La citation en question : <br/>
|
La citation en question : <br/>
|
||||||
@ -65,7 +57,7 @@ exports.emailQuoteTemplate = (isValid, quote, frontendLink) => `
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</center>
|
</center>
|
||||||
`
|
`;
|
||||||
|
|
||||||
exports.emailUserTemplate = (subtitle, buttonText, url, footerText) => `
|
exports.emailUserTemplate = (subtitle, buttonText, url, footerText) => `
|
||||||
<center>
|
<center>
|
||||||
@ -115,4 +107,4 @@ exports.emailUserTemplate = (subtitle, buttonText, url, footerText) => `
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</center>
|
</center>
|
||||||
`
|
`;
|
@ -10,9 +10,9 @@ const errors = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
requiredFields: {
|
requiredFields: {
|
||||||
message: 'Vous devez remplir tous les champs...',
|
message: "Vous devez remplir tous les champs...",
|
||||||
statusCode: 400
|
statusCode: 400
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = errors
|
module.exports = errors;
|
@ -1,6 +1,6 @@
|
|||||||
const nodemailer = require('nodemailer')
|
const nodemailer = require('nodemailer');
|
||||||
const { EMAIL_INFO } = require('./config')
|
const { EMAIL_INFO } = require('./config');
|
||||||
|
|
||||||
const transporter = nodemailer.createTransport(EMAIL_INFO)
|
const transporter = nodemailer.createTransport(EMAIL_INFO);
|
||||||
|
|
||||||
module.exports = transporter
|
module.exports = transporter;
|
@ -1,19 +1,20 @@
|
|||||||
const { randomNumberOutput } = require('./main/randomNumber')
|
const { randomNumberOutput } = require('./main/randomNumber');
|
||||||
const convertRomanArabicNumbersOutput = require('./main/convertRomanArabicNumbers')
|
const convertRomanArabicNumbersOutput = require('./main/convertRomanArabicNumbers');
|
||||||
const convertDistanceOutput = require('./main/convertDistance')
|
const convertDistanceOutput = require('./main/convertDistance');
|
||||||
const convertTemperatureOutput = require('./main/convertTemperature')
|
const convertTemperatureOutput = require('./main/convertTemperature');
|
||||||
const armstrongNumberOutput = require('./main/armstrongNumber')
|
const armstrongNumberOutput = require('./main/armstrongNumber');
|
||||||
const weatherRequestOutput = require('./main/weatherRequest')
|
const weatherRequestOutput = require('./main/weatherRequest');
|
||||||
const convertCurrencyOutput = require('./main/convertCurrency')
|
const convertCurrencyOutput = require('./main/convertCurrency');
|
||||||
const calculateAgeOutput = require('./main/calculateAge')
|
const calculateAgeOutput = require('./main/calculateAge');
|
||||||
const heapAlgorithmOutput = require('./main/heapAlgorithm')
|
const heapAlgorithmOutput = require('./main/heapAlgorithm');
|
||||||
const convertEncodingOutput = require('./main/convertEncoding')
|
const convertEncodingOutput = require('./main/convertEncoding');
|
||||||
const randomQuote = require('./main/randomQuote')
|
const randomQuote = require('./main/randomQuote');
|
||||||
const rightPriceOutput = require('./main/rightPrice')
|
const linkShortener = require('./main/linkShortener');
|
||||||
const isPalindromeOutput = require('./main/isPalindrome')
|
const rightPriceOutput = require('./main/rightPrice');
|
||||||
const findLongestWordOutput = require('./main/findLongestWord')
|
const isPalindromeOutput = require('./main/isPalindrome');
|
||||||
const fibonacciOutput = require('./main/fibonacci')
|
const findLongestWordOutput = require('./main/findLongestWord');
|
||||||
const sortArrayOutput = require('./main/sortArray')
|
const fibonacciOutput = require('./main/fibonacci');
|
||||||
|
const sortArrayOutput = require('./main/sortArray');
|
||||||
|
|
||||||
const functionObject = {
|
const functionObject = {
|
||||||
randomNumber : randomNumberOutput,
|
randomNumber : randomNumberOutput,
|
||||||
@ -27,16 +28,17 @@ const functionObject = {
|
|||||||
heapAlgorithm : heapAlgorithmOutput,
|
heapAlgorithm : heapAlgorithmOutput,
|
||||||
convertEncoding : convertEncodingOutput,
|
convertEncoding : convertEncodingOutput,
|
||||||
randomQuote : randomQuote,
|
randomQuote : randomQuote,
|
||||||
|
linkShortener : linkShortener,
|
||||||
rightPrice : rightPriceOutput,
|
rightPrice : rightPriceOutput,
|
||||||
isPalindrome : isPalindromeOutput,
|
isPalindrome : isPalindromeOutput,
|
||||||
findLongestWord : findLongestWordOutput,
|
findLongestWord : findLongestWordOutput,
|
||||||
fibonacci : fibonacciOutput,
|
fibonacci : fibonacciOutput,
|
||||||
sortArray: sortArrayOutput
|
sortArray : sortArrayOutput,
|
||||||
}
|
};
|
||||||
|
|
||||||
// Choisi la fonction à exécuter
|
// Choisi la fonction à exécuter
|
||||||
function functionToExecute(option) {
|
function functionToExecute(option) {
|
||||||
return functionObject[option]
|
return functionObject[option];
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = functionToExecute
|
module.exports = functionToExecute;
|
@ -1,6 +1,6 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
const formatNumberResult = require('../secondary/formatNumberResult')
|
const formatNumberResult = require('../secondary/formatNumberResult');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Vérifie si un nombre fait partie des nombres d'Armstrong.
|
* @description Vérifie si un nombre fait partie des nombres d'Armstrong.
|
||||||
@ -9,51 +9,38 @@ const formatNumberResult = require('../secondary/formatNumberResult')
|
|||||||
* @examples armstrongNumber(153) → 153 est un nombre d'Armstrong, car 1<sup>3</sup> + 5<sup>3</sup> + 3<sup>3</sup> = 153.
|
* @examples armstrongNumber(153) → 153 est un nombre d'Armstrong, car 1<sup>3</sup> + 5<sup>3</sup> + 3<sup>3</sup> = 153.
|
||||||
*/
|
*/
|
||||||
function armstrongNumber(number) {
|
function armstrongNumber(number) {
|
||||||
const numberString = number.toString()
|
let numberString = number.toString();
|
||||||
const numberStringLength = numberString.length
|
let numberStringLength = numberString.length;
|
||||||
|
|
||||||
let result = 0
|
let result = 0;
|
||||||
let resultString = ''
|
let resultString = "";
|
||||||
for (let index = 0; index < numberStringLength; index++) {
|
for (let index = 0; index < numberStringLength; index++) {
|
||||||
result = result + parseInt(numberString[index]) ** numberStringLength
|
result = result + parseInt(numberString[index]) ** numberStringLength;
|
||||||
resultString =
|
resultString = resultString + " + " + numberString[index] + "<sup>" + numberStringLength + "</sup>";
|
||||||
resultString +
|
|
||||||
' + ' +
|
|
||||||
numberString[index] +
|
|
||||||
'<sup>' +
|
|
||||||
numberStringLength +
|
|
||||||
'</sup>'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const formattedNumber = formatNumberResult(number)
|
const formattedNumber = formatNumberResult(number);
|
||||||
const isArmstrongNumber = result === number
|
const isArmstrongNumber = (result === number);
|
||||||
return {
|
return {
|
||||||
isArmstrongNumber,
|
isArmstrongNumber,
|
||||||
resultHTML: `<p>${formattedNumber} ${
|
resultHTML: `<p>${formattedNumber} ${isArmstrongNumber ? "est" : "n'est pas"} un nombre d'Armstrong, car ${resultString.slice(2)} = ${formatNumberResult(result)}.</p>`
|
||||||
isArmstrongNumber ? 'est' : "n'est pas"
|
|
||||||
} un nombre d'Armstrong, car ${resultString.slice(
|
|
||||||
2
|
|
||||||
)} = ${formatNumberResult(result)}.</p>`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = armstrongNumberOutput = ({ res, next }, argsObject) => {
|
||||||
let { number } = argsObject
|
let { number } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!number) {
|
if (!(number)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si ce n'est pas un nombre
|
// Si ce n'est pas un nombre
|
||||||
number = parseInt(number)
|
number = parseInt(number);
|
||||||
if (isNaN(number) || number <= 0) {
|
if (isNaN(number) || number <= 0) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Veuillez rentré un nombre valide.", statusCode: 400 });
|
||||||
message: 'Veuillez rentré un nombre valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).json(armstrongNumber(number))
|
return res.status(200).json(armstrongNumber(number));
|
||||||
}
|
}
|
@ -1,60 +1,50 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const moment = require('moment')
|
const moment = require('moment');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
|
|
||||||
function calculateAge (
|
function calculateAge(currentDate, { birthDateDay, birthDateMonth, birthDateYear }) {
|
||||||
currentDate,
|
const day = currentDate.getDate();
|
||||||
{ birthDateDay, birthDateMonth, birthDateYear }
|
const month = currentDate.getMonth();
|
||||||
) {
|
const currentDateMoment = moment([currentDate.getFullYear(), month, day]);
|
||||||
const day = currentDate.getDate()
|
const birthDateMoment = moment([birthDateYear, birthDateMonth, birthDateDay]);
|
||||||
const month = currentDate.getMonth()
|
|
||||||
const currentDateMoment = moment([currentDate.getFullYear(), month, day])
|
|
||||||
const birthDateMoment = moment([birthDateYear, birthDateMonth, birthDateDay])
|
|
||||||
|
|
||||||
// Calcule l'âge - Moment.js
|
// Calcule l'âge - Moment.js
|
||||||
const ageYears = currentDateMoment.diff(birthDateMoment, 'year')
|
const ageYears = currentDateMoment.diff(birthDateMoment, 'year');
|
||||||
birthDateMoment.add(ageYears, 'years')
|
birthDateMoment.add(ageYears, 'years');
|
||||||
const ageMonths = currentDateMoment.diff(birthDateMoment, 'months')
|
const ageMonths = currentDateMoment.diff(birthDateMoment, 'months');
|
||||||
birthDateMoment.add(ageMonths, 'months')
|
birthDateMoment.add(ageMonths, 'months');
|
||||||
const ageDays = currentDateMoment.diff(birthDateMoment, 'days')
|
const ageDays = currentDateMoment.diff(birthDateMoment, 'days');
|
||||||
|
|
||||||
const isBirthday = birthDateDay === day && birthDateMonth === month
|
const isBirthday = (birthDateDay === day && birthDateMonth === month);
|
||||||
return { ageYears, ageMonths, ageDays, isBirthday }
|
return { ageYears, ageMonths, ageDays, isBirthday };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = calculateAgeOutput = ({ res, next }, argsObject) => {
|
||||||
const { birthDate } = argsObject
|
let { birthDate } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!birthDate) {
|
if (!(birthDate)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
const birthDateDay = parseInt(birthDate.substring(0, 2))
|
const birthDateDay = parseInt(birthDate.substring(0, 2));
|
||||||
const birthDateMonth = parseInt(birthDate.substring(3, 5) - 1)
|
const birthDateMonth = parseInt((birthDate.substring(3, 5)) - 1);
|
||||||
const birthDateYear = parseInt(birthDate.substring(6, 10))
|
const birthDateYear = parseInt(birthDate.substring(6, 10));
|
||||||
|
|
||||||
// Si ce n'est pas une date valide
|
// Si ce n'est pas une date valide
|
||||||
const currentDate = new Date()
|
const currentDate = new Date();
|
||||||
const birthDateObject = new Date(birthDateYear, birthDateMonth, birthDateDay)
|
const birthDateObject = new Date(birthDateYear, birthDateMonth, birthDateDay);
|
||||||
const result = calculateAge(currentDate, {
|
const result = calculateAge(currentDate, { birthDateYear, birthDateMonth, birthDateDay });
|
||||||
birthDateYear,
|
if ((currentDate < birthDateObject) || isNaN(result.ageYears)) {
|
||||||
birthDateMonth,
|
return errorHandling(next, { message: "Veuillez rentré une date valide...", statusCode: 400 });
|
||||||
birthDateDay
|
|
||||||
})
|
|
||||||
if (currentDate < birthDateObject || isNaN(result.ageYears)) {
|
|
||||||
return errorHandling(next, {
|
|
||||||
message: 'Veuillez rentré une date valide...',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let resultHTML
|
let resultHTML;
|
||||||
if (result.isBirthday) {
|
if (result.isBirthday) {
|
||||||
resultHTML = `<p>Vous avez ${result.ageYears} ans. Joyeux Anniversaire! 🥳</p>`
|
resultHTML = `<p>Vous avez ${result.ageYears} ans. Joyeux Anniversaire! 🥳</p>`;
|
||||||
} else {
|
} else {
|
||||||
resultHTML = `<p>Vous avez ${result.ageYears} ans, ${result.ageMonths} mois et ${result.ageDays} jour(s).</p>`
|
resultHTML = `<p>Vous avez ${result.ageYears} ans, ${result.ageMonths} mois et ${result.ageDays} jour(s).</p>`;
|
||||||
}
|
}
|
||||||
return res.status(200).json({ ...result, resultHTML })
|
return res.status(200).json({ ...result, resultHTML });
|
||||||
}
|
}
|
@ -1,53 +1,37 @@
|
|||||||
const axios = require('axios')
|
const axios = require('axios');
|
||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
const formatNumberResult = require('../secondary/formatNumberResult')
|
const formatNumberResult = require('../secondary/formatNumberResult');
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = convertCurrencyOutput = ({ res, next }, argsObject) => {
|
||||||
let { number, baseCurrency, finalCurrency } = argsObject
|
let { number, baseCurrency, finalCurrency } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!(number && baseCurrency && finalCurrency)) {
|
if (!(number && baseCurrency && finalCurrency)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si ce n'est pas un nombre
|
// Si ce n'est pas un nombre
|
||||||
number = parseFloat(number)
|
number = parseFloat(number);
|
||||||
if (isNaN(number)) {
|
if (isNaN(number)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Veuillez rentré un nombre valide.", statusCode: 400 });
|
||||||
message: 'Veuillez rentré un nombre valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
axios
|
axios.get(`https://api.exchangeratesapi.io/latest?base=${baseCurrency}`)
|
||||||
.get(`https://api.exchangeratesapi.io/latest?base=${baseCurrency}`)
|
.then((response) => {
|
||||||
.then(response => {
|
const rate = response.data.rates[finalCurrency];
|
||||||
const rate = response.data.rates[finalCurrency]
|
|
||||||
if (!rate) {
|
if (!rate) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La devise n'existe pas.", statusCode: 404 });
|
||||||
message: "La devise n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const result = rate * number
|
const result = rate * number;
|
||||||
const dateObject = new Date(response.data.date)
|
const dateObject = new Date(response.data.date);
|
||||||
const year = dateObject.getFullYear()
|
const year = dateObject.getFullYear();
|
||||||
const day = ('0' + dateObject.getDate()).slice(-2)
|
const day = ('0'+(dateObject.getDate())).slice(-2);
|
||||||
const month = ('0' + (dateObject.getMonth() + 1)).slice(-2)
|
const month = ('0'+(dateObject.getMonth()+1)).slice(-2);
|
||||||
const date = `${day}/${month}/${year}`
|
const date = `${day}/${month}/${year}`;
|
||||||
const resultHTML = `<p>${formatNumberResult(number)} ${
|
const resultHTML = `<p>${formatNumberResult(number)} ${response.data.base} = ${formatNumberResult(result.toFixed(2))} ${finalCurrency}</p><p>Dernier rafraîchissement du taux d'échange : ${date}</p>`;
|
||||||
response.data.base
|
return res.status(200).json({ date, result, resultHTML });
|
||||||
} = ${formatNumberResult(
|
|
||||||
result.toFixed(2)
|
|
||||||
)} ${finalCurrency}</p><p>Dernier rafraîchissement du taux d'échange : ${date}</p>`
|
|
||||||
return res.status(200).json({ date, result, resultHTML })
|
|
||||||
})
|
})
|
||||||
.catch(() =>
|
.catch(() => errorHandling(next, { message: "La devise n'existe pas.", statusCode: 404 }));
|
||||||
errorHandling(next, {
|
|
||||||
message: "La devise n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
}
|
@ -1,34 +1,8 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields, generalError } = require('../../config/errors')
|
const { requiredFields, generalError } = require('../../config/errors');
|
||||||
const formatNumberResult = require('../secondary/formatNumberResult')
|
const formatNumberResult = require('../secondary/formatNumberResult');
|
||||||
|
|
||||||
const correspondancesDistance = [
|
const correspondancesDistance = ["pm", null, null, "nm", null, null, "µm", null, null, "mm", "cm", "dm", "m", "dam", "hm", "km", null, null, "Mm", null, null, "Gm", null, null, "Tm"];
|
||||||
'pm',
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
'nm',
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
'µm',
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
'mm',
|
|
||||||
'cm',
|
|
||||||
'dm',
|
|
||||||
'm',
|
|
||||||
'dam',
|
|
||||||
'hm',
|
|
||||||
'km',
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
'Mm',
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
'Gm',
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
'Tm'
|
|
||||||
]
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Convertis la longueur (distance) avec les unités allant de picomètre au Téramètre.
|
* @description Convertis la longueur (distance) avec les unités allant de picomètre au Téramètre.
|
||||||
@ -40,45 +14,38 @@ const correspondancesDistance = [
|
|||||||
* @examples convertDistance(500, 'cm', 'm') → { resultNumber: 5, resultString: "5 m" }
|
* @examples convertDistance(500, 'cm', 'm') → { resultNumber: 5, resultString: "5 m" }
|
||||||
*/
|
*/
|
||||||
function convertDistance(firstValue, unitFirstValue, unitFinalValue) {
|
function convertDistance(firstValue, unitFirstValue, unitFinalValue) {
|
||||||
const index1 = correspondancesDistance.indexOf(unitFirstValue)
|
const index1 = correspondancesDistance.indexOf(unitFirstValue);
|
||||||
const index2 = correspondancesDistance.indexOf(unitFinalValue)
|
const index2 = correspondancesDistance.indexOf(unitFinalValue);
|
||||||
if (index1 !== -1 && index2 !== -1) {
|
if (index1 !== -1 && index2 !== -1) {
|
||||||
const difference = index1 - index2
|
const difference = index1 - index2;
|
||||||
const result = firstValue * Math.pow(10, difference)
|
const result = firstValue * Math.pow(10, difference);
|
||||||
return {
|
return {
|
||||||
result,
|
result,
|
||||||
resultHTML: `<p>${formatNumberResult(
|
resultHTML: `<p>${formatNumberResult(firstValue)} ${unitFirstValue} = ${formatNumberResult(result)} ${unitFinalValue}</p>`
|
||||||
firstValue
|
};
|
||||||
)} ${unitFirstValue} = ${formatNumberResult(
|
|
||||||
result
|
|
||||||
)} ${unitFinalValue}</p>`
|
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = convertDistanceOutput = ({ res, next }, argsObject) => {
|
||||||
let { number, numberUnit, finalUnit } = argsObject
|
let { number, numberUnit, finalUnit } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!(number && numberUnit && finalUnit)) {
|
if (!(number && numberUnit && finalUnit)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si ce n'est pas un nombre
|
// Si ce n'est pas un nombre
|
||||||
number = parseFloat(number)
|
number = parseFloat(number);
|
||||||
if (isNaN(number)) {
|
if (isNaN(number)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Veuillez rentré un nombre valide.", statusCode: 400 });
|
||||||
message: 'Veuillez rentré un nombre valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = convertDistance(number, numberUnit, finalUnit)
|
const result = convertDistance(number, numberUnit, finalUnit);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return errorHandling(next, generalError)
|
return errorHandling(next, generalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).json(result)
|
return res.status(200).json(result);
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields, generalError } = require('../../config/errors')
|
const { requiredFields, generalError } = require('../../config/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Convertis un nombre décimal en binaire.
|
* @description Convertis un nombre décimal en binaire.
|
||||||
@ -8,11 +8,11 @@ const { requiredFields, generalError } = require('../../config/errors')
|
|||||||
* @examples decimalToBinary('2') → '10'
|
* @examples decimalToBinary('2') → '10'
|
||||||
*/
|
*/
|
||||||
function decimalToBinary(value) {
|
function decimalToBinary(value) {
|
||||||
value = Number(value)
|
value = Number(value);
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return value.toString(2)
|
return value.toString(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,11 +23,11 @@ function decimalToBinary (value) {
|
|||||||
* @examples binaryToDecimal('10') → 2
|
* @examples binaryToDecimal('10') → 2
|
||||||
*/
|
*/
|
||||||
function binaryToDecimal(value) {
|
function binaryToDecimal(value) {
|
||||||
const result = parseInt(Number(value), 2)
|
const result = parseInt(Number(value), 2);
|
||||||
if (isNaN(result)) {
|
if (isNaN(result)) {
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,11 +38,11 @@ function binaryToDecimal (value) {
|
|||||||
* @examples decimalToHexadecimal('15') → 'F'
|
* @examples decimalToHexadecimal('15') → 'F'
|
||||||
*/
|
*/
|
||||||
function decimalToHexadecimal(value) {
|
function decimalToHexadecimal(value) {
|
||||||
value = Number(value)
|
value = Number(value);
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return value.toString(16).toUpperCase()
|
return value.toString(16).toUpperCase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,11 +53,11 @@ function decimalToHexadecimal (value) {
|
|||||||
* @examples hexadecimalToDecimal('F') → 15
|
* @examples hexadecimalToDecimal('F') → 15
|
||||||
*/
|
*/
|
||||||
function hexadecimalToDecimal(value) {
|
function hexadecimalToDecimal(value) {
|
||||||
const result = parseInt(value, 16)
|
const result = parseInt(value, 16);
|
||||||
if (isNaN(result)) {
|
if (isNaN(result)) {
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,14 +68,12 @@ function hexadecimalToDecimal (value) {
|
|||||||
* @examples binaryToHexadecimal('1111') → 'F'
|
* @examples binaryToHexadecimal('1111') → 'F'
|
||||||
*/
|
*/
|
||||||
function binaryToHexadecimal(value) {
|
function binaryToHexadecimal(value) {
|
||||||
value = Number(value)
|
value = Number(value);
|
||||||
value = parseInt(value, 2)
|
value = parseInt(value, 2);
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return parseInt(value)
|
return parseInt(value).toString(16).toUpperCase();
|
||||||
.toString(16)
|
|
||||||
.toUpperCase()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,11 +84,11 @@ function binaryToHexadecimal (value) {
|
|||||||
* @examples hexadecimalToBinary('F') → '1111'
|
* @examples hexadecimalToBinary('F') → '1111'
|
||||||
*/
|
*/
|
||||||
function hexadecimalToBinary(value) {
|
function hexadecimalToBinary(value) {
|
||||||
value = parseInt(value, 16)
|
value = parseInt(value, 16);
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
return false
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return parseInt(value).toString(2)
|
return parseInt(value).toString(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,13 +102,14 @@ function hexadecimalToBinary (value) {
|
|||||||
*/
|
*/
|
||||||
function textToNumberUnicode(string) {
|
function textToNumberUnicode(string) {
|
||||||
try {
|
try {
|
||||||
let resultat = ''
|
let resultat = "";
|
||||||
for (const index in string) {
|
for (let index in string) {
|
||||||
resultat = resultat + string.codePointAt(index) + ' '
|
resultat = resultat + string.codePointAt(index) + " ";
|
||||||
}
|
}
|
||||||
return resultat
|
return resultat;
|
||||||
} catch (error) {
|
}
|
||||||
return false
|
catch(error) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,14 +121,15 @@ function textToNumberUnicode (string) {
|
|||||||
*/
|
*/
|
||||||
function numberUnicodeToText(string) {
|
function numberUnicodeToText(string) {
|
||||||
try {
|
try {
|
||||||
const array = string.split(' ')
|
const array = string.split(" ");
|
||||||
let resultat = ''
|
let resultat = "";
|
||||||
for (const index in array) {
|
for (let index in array) {
|
||||||
resultat += String.fromCodePoint(parseInt(array[index]).toString())
|
resultat += String.fromCodePoint(parseInt(array[index]).toString());
|
||||||
}
|
}
|
||||||
return resultat
|
return resultat;
|
||||||
} catch (error) {
|
}
|
||||||
return false
|
catch(error) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,21 +141,16 @@ function numberUnicodeToText (string) {
|
|||||||
*/
|
*/
|
||||||
function textToBinary(s) {
|
function textToBinary(s) {
|
||||||
try {
|
try {
|
||||||
s = unescape(encodeURIComponent(s))
|
s = unescape( encodeURIComponent(s));
|
||||||
let chr
|
let chr, i = 0, l = s.length, out = '';
|
||||||
let i = 0
|
|
||||||
const l = s.length
|
|
||||||
let out = ''
|
|
||||||
for( ; i < l; i ++ ){
|
for( ; i < l; i ++ ){
|
||||||
chr = s.charCodeAt(i).toString(2)
|
chr = s.charCodeAt( i ).toString(2);
|
||||||
while (chr.length % 8 !== 0) {
|
while(chr.length % 8 != 0 ){ chr = '0' + chr; }
|
||||||
chr = '0' + chr
|
out += chr;
|
||||||
}
|
}
|
||||||
out += chr
|
return out.replace(/(\d{8})/g, '$1 ').replace(/(^\s+|\s+$)/,'');
|
||||||
}
|
|
||||||
return out.replace(/(\d{8})/g, '$1 ').replace(/(^\s+|\s+$)/, '')
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,17 +163,14 @@ function textToBinary (s) {
|
|||||||
function binaryToText(s){
|
function binaryToText(s){
|
||||||
try {
|
try {
|
||||||
s = s.replace(/\s/g,'')
|
s = s.replace(/\s/g,'')
|
||||||
let i = 0
|
let i = 0, l = s.length, chr, out = '';
|
||||||
const l = s.length
|
|
||||||
let chr
|
|
||||||
let out = ''
|
|
||||||
for( ; i < l; i += 8){
|
for( ; i < l; i += 8){
|
||||||
chr = parseInt(s.substr(i, 8), 2).toString(16)
|
chr = parseInt( s.substr(i, 8 ), 2).toString(16);
|
||||||
out += '%' + (chr.length % 2 === 0 ? chr : '0' + chr)
|
out += '%' + ((chr.length % 2 == 0) ? chr : '0' + chr);
|
||||||
}
|
}
|
||||||
return decodeURIComponent(out)
|
return decodeURIComponent(out);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,19 +182,17 @@ function binaryToText (s) {
|
|||||||
*/
|
*/
|
||||||
function textToHexadecimal (s) {
|
function textToHexadecimal (s) {
|
||||||
try {
|
try {
|
||||||
s = unescape(encodeURIComponent(s))
|
s = unescape( encodeURIComponent( s ) );
|
||||||
let chr
|
let chr, i = 0, l = s.length, out = '';
|
||||||
let i = 0
|
|
||||||
const l = s.length
|
|
||||||
let out = ''
|
|
||||||
for( ; i < l; i++ ){
|
for( ; i < l; i++ ){
|
||||||
chr = s.charCodeAt(i).toString(16)
|
chr = s.charCodeAt( i ).toString( 16 );
|
||||||
out += chr.length % 2 === 0 ? chr : '0' + chr
|
out += ( chr.length % 2 == 0 ) ? chr : '0' + chr;
|
||||||
out += ' '
|
out += " ";
|
||||||
}
|
}
|
||||||
return out.toUpperCase()
|
return out.toUpperCase();
|
||||||
} catch (error) {
|
}
|
||||||
return false
|
catch (error) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,55 +204,39 @@ function textToHexadecimal (s) {
|
|||||||
*/
|
*/
|
||||||
function hexadecimalToText (s) {
|
function hexadecimalToText (s) {
|
||||||
try {
|
try {
|
||||||
s = s.replace(/\s/g, '')
|
s = s.replace(/\s/g,'');
|
||||||
return decodeURIComponent(s.replace(/../g, '%$&'))
|
return decodeURIComponent( s.replace( /../g, '%$&' ) );
|
||||||
} catch (error) {
|
}
|
||||||
return false
|
catch (error) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
const convertEncoding = {
|
const convertEncoding = { decimalToBinary, binaryToDecimal, decimalToHexadecimal, hexadecimalToDecimal, binaryToHexadecimal, hexadecimalToBinary, textToNumberUnicode, numberUnicodeToText, textToBinary, binaryToText, textToHexadecimal, hexadecimalToText };
|
||||||
decimalToBinary,
|
|
||||||
binaryToDecimal,
|
|
||||||
decimalToHexadecimal,
|
|
||||||
hexadecimalToDecimal,
|
|
||||||
binaryToHexadecimal,
|
|
||||||
hexadecimalToBinary,
|
|
||||||
textToNumberUnicode,
|
|
||||||
numberUnicodeToText,
|
|
||||||
textToBinary,
|
|
||||||
binaryToText,
|
|
||||||
textToHexadecimal,
|
|
||||||
hexadecimalToText
|
|
||||||
}
|
|
||||||
function executeFunction(option, value) {
|
function executeFunction(option, value) {
|
||||||
return convertEncoding[option](value)
|
return convertEncoding[option](value);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = convertEncodingOutput = ({ res, next }, argsObject) => {
|
||||||
const { value, functionName } = argsObject
|
let { value, functionName } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!(value && functionName)) {
|
if (!(value && functionName)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si la fonction n'existe pas
|
// Si la fonction n'existe pas
|
||||||
// eslint-disable-next-line
|
|
||||||
if (!convertEncoding.hasOwnProperty(functionName)) {
|
if (!convertEncoding.hasOwnProperty(functionName)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Cette conversion n'existe pas.", statusCode: 400 });
|
||||||
message: "Cette conversion n'existe pas.",
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = executeFunction(functionName, value)
|
const result = executeFunction(functionName, value);
|
||||||
|
|
||||||
// Mauvaise valeur entrée
|
// Mauvaise valeur entrée
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return errorHandling(next, generalError)
|
return errorHandling(next, generalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).json({ result, resultHTML: `<p>${result}</p>` })
|
return res.status(200).json({ result, resultHTML: `<p>${result}</p>` });
|
||||||
}
|
}
|
@ -1,23 +1,23 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields, generalError } = require('../../config/errors')
|
const { requiredFields, generalError } = require('../../config/errors');
|
||||||
const formatNumberResult = require('../secondary/formatNumberResult')
|
const formatNumberResult = require('../secondary/formatNumberResult');
|
||||||
|
|
||||||
/* Variable pour convertRomanArabicNumbers */
|
/* Variable pour convertRomanArabicNumbers */
|
||||||
const correspondancesRomainArabe = [
|
const correspondancesRomainArabe = [
|
||||||
[1000, 'M'],
|
[1000, "M"],
|
||||||
[900, 'CM'],
|
[900, "CM"],
|
||||||
[500, 'D'],
|
[500, "D"],
|
||||||
[400, 'CD'],
|
[400, "CD"],
|
||||||
[100, 'C'],
|
[100, "C"],
|
||||||
[90, 'XC'],
|
[90, "XC"],
|
||||||
[50, 'L'],
|
[50, "L"],
|
||||||
[40, 'XL'],
|
[40, "XL"],
|
||||||
[10, 'X'],
|
[10, "X"],
|
||||||
[9, 'IX'],
|
[9, "IX"],
|
||||||
[5, 'V'],
|
[5, "V"],
|
||||||
[4, 'IV'],
|
[4, "IV"],
|
||||||
[1, 'I']
|
[1, "I"],
|
||||||
]
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Convertis un nombre arabe en nombre romain.
|
* @description Convertis un nombre arabe en nombre romain.
|
||||||
@ -27,20 +27,20 @@ const correspondancesRomainArabe = [
|
|||||||
*/
|
*/
|
||||||
function convertArabicToRoman(nombre) {
|
function convertArabicToRoman(nombre) {
|
||||||
// Initialisation de la variable qui va contenir le résultat de la conversion
|
// Initialisation de la variable qui va contenir le résultat de la conversion
|
||||||
let chiffresRomains = ''
|
let chiffresRomains = "";
|
||||||
|
|
||||||
function extraireChiffreRomain(valeurLettre, lettres) {
|
function extraireChiffreRomain(valeurLettre, lettres) {
|
||||||
while (nombre >= valeurLettre) {
|
while (nombre >= valeurLettre) {
|
||||||
chiffresRomains = chiffresRomains + lettres
|
chiffresRomains = chiffresRomains + lettres;
|
||||||
nombre = nombre - valeurLettre
|
nombre = nombre - valeurLettre;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
correspondancesRomainArabe.forEach(correspondance => {
|
correspondancesRomainArabe.forEach(correspondance => {
|
||||||
extraireChiffreRomain(correspondance[0], correspondance[1])
|
extraireChiffreRomain(correspondance[0], correspondance[1]);
|
||||||
})
|
});
|
||||||
|
|
||||||
return chiffresRomains
|
return chiffresRomains;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,94 +50,74 @@ function convertArabicToRoman (nombre) {
|
|||||||
* @example convertRomanToArabic('XXIV') → 24
|
* @example convertRomanToArabic('XXIV') → 24
|
||||||
*/
|
*/
|
||||||
function convertRomanToArabic(string) {
|
function convertRomanToArabic(string) {
|
||||||
let result = 0
|
let result = 0;
|
||||||
correspondancesRomainArabe.forEach(correspondance => {
|
correspondancesRomainArabe.forEach((correspondance) => {
|
||||||
while (string.indexOf(correspondance[1]) === 0) {
|
while (string.indexOf(correspondance[1]) === 0) {
|
||||||
// Ajout de la valeur décimale au résultat
|
// Ajout de la valeur décimale au résultat
|
||||||
result += correspondance[0]
|
result += correspondance[0];
|
||||||
// Supprimer la lettre romaine correspondante du début
|
// Supprimer la lettre romaine correspondante du début
|
||||||
string = string.replace(correspondance[1], '')
|
string = string.replace(correspondance[1], '');
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
if (string !== '') {
|
if (string != '') {
|
||||||
result = 0
|
result = 0;
|
||||||
}
|
}
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
const convertRomanToArabicOutput = ({ res, next }, number) => {
|
const convertRomanToArabicOutput = ({ res, next }, number) => {
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!number) {
|
if (!(number)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formate le paramètre
|
// Formate le paramètre
|
||||||
number = number.toUpperCase()
|
number = number.toUpperCase();
|
||||||
|
|
||||||
const result = convertRomanToArabic(number)
|
const result = convertRomanToArabic(number);
|
||||||
if (result === 0) {
|
if (result === 0) {
|
||||||
return errorHandling(next, generalError)
|
return errorHandling(next, generalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res.status(200).json({ result, resultHTML: `<p><span class="important">${number}</span> s'écrit <span class="important">${result}</span> en chiffres arabes.</p>` });
|
||||||
.status(200)
|
|
||||||
.json({
|
|
||||||
result,
|
|
||||||
resultHTML: `<p><span class="important">${number}</span> s'écrit <span class="important">${result}</span> en chiffres arabes.</p>`
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const convertArabicToRomanOutput = ({ res, next }, number) => {
|
const convertArabicToRomanOutput = ({ res, next }, number) => {
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!number) {
|
if (!(number)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si ce n'est pas un nombre
|
// Si ce n'est pas un nombre
|
||||||
number = parseInt(number)
|
number = parseInt(number);
|
||||||
if (isNaN(number)) {
|
if (isNaN(number)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Veuillez rentré un nombre valide.", statusCode: 400 });
|
||||||
message: 'Veuillez rentré un nombre valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = convertArabicToRoman(number)
|
const result = convertArabicToRoman(number);
|
||||||
return res
|
return res.status(200).json({ result, resultHTML: `<p><span class="important">${formatNumberResult(number)}</span> s'écrit <span class="important">${result}</span> en chiffres romains.</p>` });
|
||||||
.status(200)
|
|
||||||
.json({
|
|
||||||
result,
|
|
||||||
resultHTML: `<p><span class="important">${formatNumberResult(
|
|
||||||
number
|
|
||||||
)}</span> s'écrit <span class="important">${result}</span> en chiffres romains.</p>`
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const convertRomanArabicObject = {
|
const convertRomanArabicObject = { convertRomanToArabicOutput, convertArabicToRomanOutput };
|
||||||
convertRomanToArabicOutput,
|
|
||||||
convertArabicToRomanOutput
|
|
||||||
}
|
|
||||||
function executeFunction(option, value, { res, next }) {
|
function executeFunction(option, value, { res, next }) {
|
||||||
return convertRomanArabicObject[option]({ res, next }, value)
|
return convertRomanArabicObject[option]({ res, next}, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = convertRomanArabicNumbersOutput = ({ res, next }, argsObject) => {
|
||||||
const { value, functionName } = argsObject
|
let { value, functionName } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!(value && functionName)) {
|
if (!(value && functionName)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si la fonction n'existe pas
|
// Si la fonction n'existe pas
|
||||||
// eslint-disable-next-line
|
|
||||||
if (!convertRomanArabicObject.hasOwnProperty(functionName)) {
|
if (!convertRomanArabicObject.hasOwnProperty(functionName)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Cette conversion n'existe pas.", statusCode: 400 });
|
||||||
message: "Cette conversion n'existe pas.",
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
executeFunction(functionName, value, { res, next })
|
executeFunction(functionName, value, { res, next });
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields, generalError } = require('../../config/errors')
|
const { requiredFields, generalError } = require('../../config/errors');
|
||||||
const formatNumberResult = require('../secondary/formatNumberResult')
|
const formatNumberResult = require('../secondary/formatNumberResult');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Convertis des °C en °F et l'inverse aussi.
|
* @description Convertis des °C en °F et l'inverse aussi.
|
||||||
@ -10,44 +10,41 @@ const formatNumberResult = require('../secondary/formatNumberResult')
|
|||||||
* @examples convertTemperature(23, '°F') → { result: 73.4, resultHTML: "73.4 °F" }
|
* @examples convertTemperature(23, '°F') → { result: 73.4, resultHTML: "73.4 °F" }
|
||||||
*/
|
*/
|
||||||
function convertTemperature(degree, unit) {
|
function convertTemperature(degree, unit) {
|
||||||
let temperatureValue = 0
|
let temperatureValue = 0;
|
||||||
if (unit === '°C') {
|
if (unit === "°C") {
|
||||||
temperatureValue = ((degree - 32) * 5) / 9
|
temperatureValue = (degree - 32) * 5/9;
|
||||||
} else if (unit === '°F') {
|
}
|
||||||
temperatureValue = (degree * 9) / 5 + 32
|
else if (unit === "°F") {
|
||||||
} else {
|
temperatureValue = ((degree * 9/5) + 32);
|
||||||
return false
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
result: temperatureValue,
|
result: temperatureValue,
|
||||||
resultHTML: `<p>${formatNumberResult(degree)} ${
|
resultHTML: `<p>${formatNumberResult(degree)} ${(unit === '°C') ? "°F" : "°C"} = ${formatNumberResult(temperatureValue)} ${unit}</p>`
|
||||||
unit === '°C' ? '°F' : '°C'
|
};
|
||||||
} = ${formatNumberResult(temperatureValue)} ${unit}</p>`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = convertTemperatureOutput = ({ res, next }, argsObject) => {
|
||||||
let { degree, unitToConvert } = argsObject
|
let { degree, unitToConvert } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!(degree && unitToConvert)) {
|
if (!(degree && unitToConvert)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si ce n'est pas un nombre
|
// Si ce n'est pas un nombre
|
||||||
degree = parseFloat(degree)
|
degree = parseFloat(degree);
|
||||||
if (isNaN(degree)) {
|
if (isNaN(degree)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Veuillez rentré un nombre valide.", statusCode: 400 });
|
||||||
message: 'Veuillez rentré un nombre valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = convertTemperature(degree, unitToConvert)
|
const result = convertTemperature(degree, unitToConvert);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return errorHandling(next, generalError)
|
return errorHandling(next, generalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).json(result)
|
return res.status(200).json(result);
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
const formatNumberResult = require('../secondary/formatNumberResult')
|
const formatNumberResult = require('../secondary/formatNumberResult');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Calcule les counter premiers nombres de la suite de fibonacci.
|
* @description Calcule les counter premiers nombres de la suite de fibonacci.
|
||||||
@ -8,48 +8,39 @@ const formatNumberResult = require('../secondary/formatNumberResult')
|
|||||||
*/
|
*/
|
||||||
function fibonacci(counter, result = [], a = 0, b = 1) {
|
function fibonacci(counter, result = [], a = 0, b = 1) {
|
||||||
if (counter === 0) {
|
if (counter === 0) {
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
counter--
|
counter--;
|
||||||
result.push(a)
|
result.push(a);
|
||||||
return fibonacci(counter, result, b, a + b)
|
return fibonacci(counter, result, b, a + b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = fibonacciOutput = ({ res, next }, argsObject) => {
|
||||||
let { counter } = argsObject
|
let { counter } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!counter) {
|
if (!(counter)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si ce n'est pas un nombre
|
// Si ce n'est pas un nombre
|
||||||
counter = parseInt(counter)
|
counter = parseInt(counter);
|
||||||
if (isNaN(counter)) {
|
if (isNaN(counter)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Veuillez rentré un nombre valide.", statusCode: 400 });
|
||||||
message: 'Veuillez rentré un nombre valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si le nombre dépasse LIMIT_COUNTER
|
// Si le nombre dépasse LIMIT_COUNTER
|
||||||
const LIMIT_COUNTER = 51
|
const LIMIT_COUNTER = 51;
|
||||||
if (counter >= LIMIT_COUNTER) {
|
if (counter >= LIMIT_COUNTER) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: `Par souci de performance, vous ne pouvez pas exécuter cette fonction avec un compteur dépassant ${LIMIT_COUNTER - 1}.`, statusCode: 400 });
|
||||||
message: `Par souci de performance, vous ne pouvez pas exécuter cette fonction avec un compteur dépassant ${LIMIT_COUNTER -
|
|
||||||
1}.`,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = fibonacci(counter)
|
const result = fibonacci(counter);
|
||||||
const resultFormatted = result.map(number => formatNumberResult(number))
|
const resultFormatted = result.map((number) => formatNumberResult(number));
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
result,
|
result,
|
||||||
resultFormatted,
|
resultFormatted,
|
||||||
resultHTML: `<p>Les ${counter} premiers nombres de la suite de fibonacci :<br/> ${resultFormatted.join(
|
resultHTML: `<p>Les ${counter} premiers nombres de la suite de fibonacci :<br/> ${resultFormatted.join(', ')}</p>`
|
||||||
', '
|
});
|
||||||
)}</p>`
|
|
||||||
})
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Renvoie le mot le plus long d'une chaîne de caractères
|
* @description Renvoie le mot le plus long d'une chaîne de caractères
|
||||||
@ -8,32 +8,32 @@ const { requiredFields } = require('../../config/errors')
|
|||||||
* @example findLongestWord('Chaîne de caractères') → 'caractères'
|
* @example findLongestWord('Chaîne de caractères') → 'caractères'
|
||||||
*/
|
*/
|
||||||
function findLongestWord(string) {
|
function findLongestWord(string) {
|
||||||
const arrayString = string.split(' ')
|
const arrayString = string.split(" ");
|
||||||
let stringLength = 0
|
let stringLength = 0;
|
||||||
let result = ''
|
let result = "";
|
||||||
|
|
||||||
arrayString.forEach(element => {
|
arrayString.forEach((element) => {
|
||||||
if (element.length > stringLength) {
|
if (element.length > stringLength) {
|
||||||
result = element
|
result = element;
|
||||||
stringLength = element.length
|
stringLength = element.length;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = findLongestWordOutput = ({ res, next }, argsObject) => {
|
||||||
const { string } = argsObject
|
const { string } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!string) {
|
if (!(string)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = findLongestWord(string)
|
const result = findLongestWord(string);
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
result,
|
result,
|
||||||
resultHTML: `<p>Le mot le plus long est : <br/>"${result}"</p>`
|
resultHTML: `<p>Le mot le plus long est : <br/>"${result}"</p>`
|
||||||
})
|
});
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
const formatNumberResult = require('../secondary/formatNumberResult')
|
const formatNumberResult = require('../secondary/formatNumberResult');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Retourne un tableau contenant toutes les possibilités d'anagramme d'un mot.
|
* @description Retourne un tableau contenant toutes les possibilités d'anagramme d'un mot.
|
||||||
@ -9,56 +9,44 @@ const formatNumberResult = require('../secondary/formatNumberResult')
|
|||||||
* @examples heapAlgorithm('abc') → ["abc", "acb", "bac", "bca", "cab", "cba"]
|
* @examples heapAlgorithm('abc') → ["abc", "acb", "bac", "bca", "cab", "cba"]
|
||||||
*/
|
*/
|
||||||
function heapAlgorithm(string) {
|
function heapAlgorithm(string) {
|
||||||
const results = []
|
let results = [];
|
||||||
|
|
||||||
if (string.length === 1) {
|
if (string.length === 1) {
|
||||||
results.push(string)
|
results.push(string);
|
||||||
return results
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let indexString = 0; indexString < string.length; indexString++) {
|
for (let indexString = 0; indexString < string.length; indexString++) {
|
||||||
const firstChar = string[indexString]
|
const firstChar = string[indexString];
|
||||||
const charsLeft =
|
const charsLeft = string.substring(0, indexString) + string.substring(indexString + 1);
|
||||||
string.substring(0, indexString) + string.substring(indexString + 1)
|
const innerPermutations = heapAlgorithm(charsLeft);
|
||||||
const innerPermutations = heapAlgorithm(charsLeft)
|
for (let indexPermutation = 0; indexPermutation < innerPermutations.length; indexPermutation++) {
|
||||||
for (
|
results.push(firstChar + innerPermutations[indexPermutation]);
|
||||||
let indexPermutation = 0;
|
|
||||||
indexPermutation < innerPermutations.length;
|
|
||||||
indexPermutation++
|
|
||||||
) {
|
|
||||||
results.push(firstChar + innerPermutations[indexPermutation])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = heapAlgorithmOutput = ({ res, next }, argsObject) => {
|
||||||
const { string } = argsObject
|
let { string } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!string) {
|
if (!(string)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si la chaîne de caractère dépasse LIMIT_CHARACTERS caractères
|
// Si la chaîne de caractère dépasse LIMIT_CHARACTERS caractères
|
||||||
const LIMIT_CHARACTERS = 7
|
const LIMIT_CHARACTERS = 7;
|
||||||
if (string.length > LIMIT_CHARACTERS) {
|
if (string.length > LIMIT_CHARACTERS) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: `Par souci de performance, vous ne pouvez pas exécuter cette fonction avec un mot dépassant ${LIMIT_CHARACTERS} caractères.`, statusCode: 400 });
|
||||||
message: `Par souci de performance, vous ne pouvez pas exécuter cette fonction avec un mot dépassant ${LIMIT_CHARACTERS} caractères.`,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = heapAlgorithm(string)
|
const result = heapAlgorithm(string);
|
||||||
let resultHTML = `<p>Il y a ${formatNumberResult(
|
let resultHTML = `<p>Il y a ${formatNumberResult(result.length)} possibilités d'anagramme pour le mot "${string}" qui contient ${string.length} caractères, la liste : <br/><br/>`;
|
||||||
result.length
|
result.forEach((string) => {
|
||||||
)} possibilités d'anagramme pour le mot "${string}" qui contient ${
|
resultHTML += string + "<br/>";
|
||||||
string.length
|
});
|
||||||
} caractères, la liste : <br/><br/>`
|
resultHTML += "</p>";
|
||||||
result.forEach(string => {
|
return res.status(200).json({ result, resultHTML });
|
||||||
resultHTML += string + '<br/>'
|
|
||||||
})
|
|
||||||
resultHTML += '</p>'
|
|
||||||
return res.status(200).json({ result, resultHTML })
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Inverse la chaîne de caractère
|
* @description Inverse la chaîne de caractère
|
||||||
@ -8,10 +8,7 @@ const { requiredFields } = require('../../config/errors')
|
|||||||
* @example reverseString('Hello') → 'olleH'
|
* @example reverseString('Hello') → 'olleH'
|
||||||
*/
|
*/
|
||||||
function reverseString(string) {
|
function reverseString(string) {
|
||||||
return string
|
return string.split("").reverse().join('');
|
||||||
.split('')
|
|
||||||
.reverse()
|
|
||||||
.join('')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,36 +20,29 @@ function reverseString (string) {
|
|||||||
* @example isPalindrome('kayak') → true
|
* @example isPalindrome('kayak') → true
|
||||||
*/
|
*/
|
||||||
function isPalindrome(string, reverseStringResult) {
|
function isPalindrome(string, reverseStringResult) {
|
||||||
return string === reverseStringResult
|
return string === reverseStringResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = isPalindromeOutput = ({ res, next }, argsObject) => {
|
||||||
let { string } = argsObject
|
let { string } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!string) {
|
if (!(string)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof string !== 'string') {
|
if (typeof string !== 'string') {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous devez rentré une chaîne de caractère valide.", statusCode: 400 });
|
||||||
message: 'Vous devez rentré une chaîne de caractère valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string = string.toLowerCase()
|
string = string.toLowerCase();
|
||||||
|
|
||||||
const reverseStringResult = reverseString(string)
|
const reverseStringResult = reverseString(string);
|
||||||
const isPalindromeResult = isPalindrome(string, reverseStringResult)
|
const isPalindromeResult = isPalindrome(string, reverseStringResult);
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
isPalindrome: isPalindromeResult,
|
isPalindrome: isPalindromeResult,
|
||||||
reverseString: reverseStringResult,
|
reverseString: reverseStringResult,
|
||||||
resultHTML: `<p>"${string}" ${
|
resultHTML: `<p>"${string}" ${(isPalindromeResult) ? "est" : "n'est pas"} un palindrome car <br/> "${string}" ${(isPalindromeResult) ? "===" : "!=="} "${reverseStringResult}"</p>`
|
||||||
isPalindromeResult ? 'est' : "n'est pas"
|
});
|
||||||
} un palindrome car <br/> "${string}" ${
|
|
||||||
isPalindromeResult ? '===' : '!=='
|
|
||||||
} "${reverseStringResult}"</p>`
|
|
||||||
})
|
|
||||||
}
|
}
|
52
api/assets/functions/main/linkShortener.js
Normal file
@ -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... <br/> <br/> <a target="_blank" rel="noopener noreferrer" href="${urlShort}">${urlShort}</a>`, 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é... <br/> <br/> <a target="_blank" rel="noopener noreferrer" href="${urlShort}">${urlShort}</a>`, 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 : <br/> <br/> <a target="_blank" rel="noopener noreferrer" href="${shortcutLinkResult}">${shortcutLinkResult}</a>`, result: shortcutLinkResult });
|
||||||
|
} catch {
|
||||||
|
console.log(error);
|
||||||
|
return errorHandling(next, serverError);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
const formatNumberResult = require('../secondary/formatNumberResult')
|
const formatNumberResult = require('../secondary/formatNumberResult');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Génère un nombre aléatoire entre un minimum inclus et un maximum inclus.
|
* @description Génère un nombre aléatoire entre un minimum inclus et un maximum inclus.
|
||||||
@ -10,38 +10,28 @@ const formatNumberResult = require('../secondary/formatNumberResult')
|
|||||||
* @examples randomNumber(1, 2) → retourne soit 1 ou 2
|
* @examples randomNumber(1, 2) → retourne soit 1 ou 2
|
||||||
*/
|
*/
|
||||||
function randomNumber(min, max) {
|
function randomNumber(min, max) {
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min
|
return Math.floor(Math.random() * (max - min +1)) + min;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
const randomNumberOutput = ({ res, next }, argsObject) => {
|
const randomNumberOutput = ({ res, next }, argsObject) => {
|
||||||
let { min, max } = argsObject
|
let { min, max } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!(min && max)) {
|
if (!(min && max)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si ce ne sont pas des nombres
|
// Si ce ne sont pas des nombres
|
||||||
min = parseInt(min)
|
min = parseInt(min);
|
||||||
max = parseInt(max)
|
max = parseInt(max);
|
||||||
if (isNaN(min) || isNaN(max)) {
|
if (isNaN(min) || isNaN(max)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Les paramètres min et max doivent être des nombres...", statusCode: 400 });
|
||||||
message: 'Les paramètres min et max doivent être des nombres...',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = randomNumber(min, max)
|
const result = randomNumber(min, max);
|
||||||
return res
|
return res.status(200).json({ result, resultHTML: `<p>Nombre aléatoire compris entre ${min} inclus et ${max} inclus : <strong>${formatNumberResult(result)}</strong></p>` });
|
||||||
.status(200)
|
|
||||||
.json({
|
|
||||||
result,
|
|
||||||
resultHTML: `<p>Nombre aléatoire compris entre ${min} inclus et ${max} inclus : <strong>${formatNumberResult(
|
|
||||||
result
|
|
||||||
)}</strong></p>`
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.randomNumber = randomNumber
|
exports.randomNumber = randomNumber;
|
||||||
exports.randomNumberOutput = randomNumberOutput
|
exports.randomNumberOutput = randomNumberOutput;
|
@ -1,24 +1,26 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { serverError } = require('../../config/errors')
|
const { serverError } = require('../../config/errors');
|
||||||
const Quotes = require('../../../models/quotes')
|
const Quotes = require('../../../models/quotes');
|
||||||
const Users = require('../../../models/users')
|
const Users = require('../../../models/users');
|
||||||
const sequelize = require('../../utils/database')
|
const sequelize = require('../../utils/database');
|
||||||
|
|
||||||
module.exports = async ({ res, next }, _argsObject) => {
|
module.exports = randomQuote = async ({ res, next }, _argsObject) => {
|
||||||
try {
|
try {
|
||||||
const quote = await Quotes.findOne({
|
const quote = await Quotes.findOne({
|
||||||
order: sequelize.random(),
|
order: sequelize.random(),
|
||||||
include: [{ model: Users, attributes: ['name', 'logo'] }],
|
include: [
|
||||||
|
{ model: Users, attributes: ["name", "logo"] }
|
||||||
|
],
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ['isValidated']
|
exclude: ["isValidated"]
|
||||||
},
|
},
|
||||||
where: {
|
where: {
|
||||||
isValidated: 1
|
isValidated: 1,
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
return res.status(200).json(quote)
|
return res.status(200).json(quote);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,60 +1,51 @@
|
|||||||
const { randomNumber } = require('./randomNumber')
|
const { randomNumber } = require('./randomNumber');
|
||||||
const errorHandling = require('../../utils/errorHandling')
|
|
||||||
const { serverError } = require('../../config/errors')
|
|
||||||
const { SCRAPER_API_KEY } = require('../../config/config')
|
|
||||||
const axios = require('axios')
|
|
||||||
const { JSDOM } = require('jsdom')
|
|
||||||
|
|
||||||
const subjectList = [
|
const subjectList = [
|
||||||
'smartphone',
|
"smartphone",
|
||||||
'pc+gamer',
|
"pc+gamer",
|
||||||
'pc+portable',
|
"pc+portable",
|
||||||
'TV',
|
"TV",
|
||||||
'casque',
|
"casque",
|
||||||
'clavier',
|
"clavier",
|
||||||
'souris',
|
"souris",
|
||||||
'ecran',
|
"ecran",
|
||||||
'jeux+vidéos'
|
"jeux+vidéos"
|
||||||
]
|
];
|
||||||
|
|
||||||
function getRandomArrayElement(array) {
|
function getRandomArrayElement(array) {
|
||||||
return array[randomNumber(0, array.length - 1)]
|
return array[randomNumber(0, array.length - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAmazonProductList(subject) {
|
async function getAmazonProductList(subject) {
|
||||||
const url = `https://www.amazon.fr/s?k=${subject}`
|
const url = `https://www.amazon.fr/s?k=${subject}`;
|
||||||
const { data } = await axios.get(
|
const Nightmare = require('nightmare')();
|
||||||
`http://api.scraperapi.com/?api_key=${SCRAPER_API_KEY}&url=${url}`
|
return await Nightmare.goto(url)
|
||||||
)
|
.wait('.s-result-item')
|
||||||
const { document } = new JSDOM(data).window
|
.evaluate(() => {
|
||||||
const amazonProductList = document.querySelectorAll('.s-result-item')
|
const amazonProductList = document.querySelectorAll('.s-result-item');
|
||||||
const productsList = []
|
const productsList = [];
|
||||||
for (const indexProduct in amazonProductList) {
|
for (let indexProduct in amazonProductList) {
|
||||||
try {
|
try {
|
||||||
const elementProduct = amazonProductList[indexProduct]
|
const elementProduct = amazonProductList[indexProduct];
|
||||||
const productImage = elementProduct.querySelector('.s-image')
|
const productImage = elementProduct.querySelector('.s-image');
|
||||||
const originalPrice = elementProduct.querySelector('.a-price-whole')
|
const originalPrice = elementProduct.querySelector(".a-price-whole").innerHTML;
|
||||||
.innerHTML
|
|
||||||
productsList.push({
|
productsList.push({
|
||||||
name: productImage.alt,
|
name: productImage["alt"],
|
||||||
image: productImage.src,
|
image: productImage["src"],
|
||||||
price: Number(originalPrice.replace(',', '.').replace(' ', ''))
|
price: Number(originalPrice.replace(",", ".").replace(" ", ""))
|
||||||
})
|
});
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
continue
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return productsList
|
return productsList;
|
||||||
|
})
|
||||||
|
.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = async ({ res, next }, _argsObject) => {
|
module.exports = rightPriceOutput = async ({ res }, _argsObject) => {
|
||||||
const subject = getRandomArrayElement(subjectList)
|
const subject = getRandomArrayElement(subjectList);
|
||||||
try {
|
const productsList = await getAmazonProductList(subject);
|
||||||
const productsList = await getAmazonProductList(subject)
|
const randomProduct = getRandomArrayElement(productsList);
|
||||||
const randomProduct = getRandomArrayElement(productsList)
|
return res.status(200).json({ subject, ...randomProduct });
|
||||||
return res.status(200).json({ subject, ...randomProduct })
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
return errorHandling(next, serverError)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,69 +1,56 @@
|
|||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
const formatNumberResult = require('../secondary/formatNumberResult')
|
const formatNumberResult = require('../secondary/formatNumberResult');
|
||||||
|
|
||||||
function minNumber(array) {
|
function minNumber(array) {
|
||||||
let minNumber = { index: 0, value: array[0] }
|
let minNumber = { index: 0, value: array[0] }
|
||||||
for (let index = 1; index < array.length; index++) {
|
for (let index = 1; index < array.length; index++) {
|
||||||
const number = array[index]
|
const number = array[index];
|
||||||
if (number < minNumber.value) {
|
if (number < minNumber.value) {
|
||||||
minNumber = { index: index, value: array[index] }
|
minNumber = { index: index, value: array[index] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return minNumber
|
return minNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortArray(array) {
|
function sortArray(array) {
|
||||||
const arrayDuplicated = [...array]
|
const arrayDuplicated = [...array];
|
||||||
const resultArray = []
|
const resultArray = [];
|
||||||
while (array.length !== resultArray.length) {
|
while (array.length !== resultArray.length) {
|
||||||
const min = minNumber(arrayDuplicated)
|
const min = minNumber(arrayDuplicated);
|
||||||
resultArray.push(min.value)
|
resultArray.push(min.value);
|
||||||
arrayDuplicated.splice(min.index, 1)
|
arrayDuplicated.splice(min.index, 1);
|
||||||
}
|
}
|
||||||
return resultArray
|
return resultArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = sortArrayOutput = ({ res, next }, argsObject) => {
|
||||||
const { numbersList } = argsObject
|
let { numbersList } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!numbersList) {
|
if (!(numbersList)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
const numbersListArray = numbersList
|
const numbersListArray = numbersList.split(',').map((number) => number.trim().replace(' ', '')).map(Number);
|
||||||
.split(',')
|
|
||||||
.map(number => number.trim().replace(' ', ''))
|
|
||||||
.map(Number)
|
|
||||||
|
|
||||||
// Si ce n'est pas une liste de nombres
|
// Si ce n'est pas une liste de nombres
|
||||||
if (numbersListArray.includes(NaN)) {
|
if (numbersListArray.includes(NaN)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous devez rentrer une liste de nombres séparée par des virgules valide.", statusCode: 400 });
|
||||||
message:
|
|
||||||
'Vous devez rentrer une liste de nombres séparée par des virgules valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si la taille du tableau dépasse LIMIT_ARRAY_LENGTH
|
// Si la taille du tableau dépasse LIMIT_ARRAY_LENGTH
|
||||||
const LIMIT_ARRAY_LENGTH = 31
|
const LIMIT_ARRAY_LENGTH = 31;
|
||||||
if (numbersListArray.length >= LIMIT_ARRAY_LENGTH) {
|
if (numbersListArray.length >= LIMIT_ARRAY_LENGTH) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: `Par souci de performance, vous ne pouvez pas exécuter cette fonction avec une liste de nombres dépassant ${LIMIT_ARRAY_LENGTH - 1} nombres.`, statusCode: 400 });
|
||||||
message: `Par souci de performance, vous ne pouvez pas exécuter cette fonction avec une liste de nombres dépassant ${LIMIT_ARRAY_LENGTH -
|
|
||||||
1} nombres.`,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = sortArray(numbersListArray)
|
const result = sortArray(numbersListArray);
|
||||||
const resultFormatted = result.map(number => formatNumberResult(number))
|
const resultFormatted = result.map((number) => formatNumberResult(number));
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
result,
|
result,
|
||||||
resultFormatted,
|
resultFormatted,
|
||||||
resultHTML: `<p>La liste de nombres dans l'ordre croissant :<br/> ${resultFormatted.join(
|
resultHTML: `<p>La liste de nombres dans l'ordre croissant :<br/> ${resultFormatted.join(', ')}</p>`
|
||||||
', '
|
});
|
||||||
)}</p>`
|
|
||||||
})
|
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
const axios = require('axios')
|
const axios = require('axios');
|
||||||
const Queue = require('smart-request-balancer')
|
const Queue = require('smart-request-balancer');
|
||||||
const errorHandling = require('../../utils/errorHandling')
|
const errorHandling = require('../../utils/errorHandling');
|
||||||
const { requiredFields } = require('../../config/errors')
|
const { requiredFields } = require('../../config/errors');
|
||||||
const { WEATHER_API_KEY } = require('../../config/config')
|
const { WEATHER_API_KEY } = require('../../config/config');
|
||||||
const dateTimeUTC = require('../secondary/dateTimeManagement')
|
const dateTimeUTC = require('../secondary/dateTimeManagement');
|
||||||
const capitalize = require('../secondary/capitalize')
|
const capitalize = require('../secondary/capitalize');
|
||||||
|
|
||||||
const queue = new Queue({
|
const queue = new Queue({
|
||||||
/*
|
/*
|
||||||
@ -17,57 +17,30 @@ const queue = new Queue({
|
|||||||
rate: 50,
|
rate: 50,
|
||||||
limit: 60,
|
limit: 60,
|
||||||
priority: 1
|
priority: 1
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
})
|
|
||||||
|
|
||||||
/* OUTPUTS */
|
/* OUTPUTS */
|
||||||
module.exports = ({ res, next }, argsObject) => {
|
module.exports = weatherRequestOutput = ({ res, next }, argsObject) => {
|
||||||
let { cityName } = argsObject
|
let { cityName } = argsObject;
|
||||||
|
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!cityName) {
|
if (!(cityName)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
cityName = cityName.split(' ').join('+')
|
cityName = cityName.split(' ').join('+');
|
||||||
|
|
||||||
// Récupère les données météo grâce à l'API : openweathermap.org. (→ avec limite de 50 requêtes par minute)
|
// Récupère les données météo grâce à l'API : openweathermap.org. (→ avec limite de 50 requêtes par minute)
|
||||||
queue.request(
|
queue.request(() => {
|
||||||
() => {
|
axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${cityName}&lang=fr&units=metric&appid=${WEATHER_API_KEY}`)
|
||||||
axios
|
.then((response) =>{
|
||||||
.get(
|
const json = response.data;
|
||||||
`https://api.openweathermap.org/data/2.5/weather?q=${cityName}&lang=fr&units=metric&appid=${WEATHER_API_KEY}`
|
const showDateTimeValue = dateTimeUTC((json.timezone / 60 / 60).toString()).showDateTimeValue;
|
||||||
)
|
const resultHTML = `<p>🌎 Position : <a href="https://www.google.com/maps/search/?api=1&query=${json.coord.lat},${json.coord.lon}" rel="noopener noreferrer" target="_blank">${json.name}, ${json.sys.country}</a><br/>⏰ Date et heure : ${showDateTimeValue} <br/>☁️ Météo : ${capitalize(json.weather[0].description)}<br/>🌡️ Température : ${json.main.temp} °C<br/> 💧 Humidité : ${json.main.humidity}% <br/> <img src="https://openweathermap.org/img/wn/${json.weather[0].icon}@2x.png"/></p>`;
|
||||||
.then(response => {
|
return res.status(200).json({ result: json, resultHTML });
|
||||||
const json = response.data
|
|
||||||
const showDateTimeValue = dateTimeUTC(
|
|
||||||
(json.timezone / 60 / 60).toString()
|
|
||||||
).showDateTimeValue
|
|
||||||
const resultHTML = `<p>🌎 Position : <a href="https://www.google.com/maps/search/?api=1&query=${
|
|
||||||
json.coord.lat
|
|
||||||
},${json.coord.lon}" rel="noopener noreferrer" target="_blank">${
|
|
||||||
json.name
|
|
||||||
}, ${
|
|
||||||
json.sys.country
|
|
||||||
}</a><br/>⏰ Date et heure : ${showDateTimeValue} <br/>☁️ Météo : ${capitalize(
|
|
||||||
json.weather[0].description
|
|
||||||
)}<br/>🌡️ Température : ${json.main.temp} °C<br/> 💧 Humidité : ${
|
|
||||||
json.main.humidity
|
|
||||||
}% <br/> <img src="https://openweathermap.org/img/wn/${
|
|
||||||
json.weather[0].icon
|
|
||||||
}@2x.png"/></p>`
|
|
||||||
return res.status(200).json({ result: json, resultHTML })
|
|
||||||
})
|
})
|
||||||
.catch(() =>
|
.catch(() => errorHandling(next, { message: "La ville n'existe pas (dans l'API de openweathermap.org).", statusCode: 404 }));
|
||||||
errorHandling(next, {
|
}, 'everyone', 'weatherRequest');
|
||||||
message:
|
|
||||||
"La ville n'existe pas (dans l'API de openweathermap.org).",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
)
|
|
||||||
},
|
|
||||||
'everyone',
|
|
||||||
'weatherRequest'
|
|
||||||
)
|
|
||||||
}
|
}
|
@ -9,4 +9,4 @@ function capitalize (s) {
|
|||||||
return s.charAt(0).toUpperCase() + s.slice(1)
|
return s.charAt(0).toUpperCase() + s.slice(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = capitalize
|
module.exports = capitalize;
|
@ -5,12 +5,12 @@
|
|||||||
* @examples dateTimeUTC('0')
|
* @examples dateTimeUTC('0')
|
||||||
*/
|
*/
|
||||||
function dateTimeUTC(utc) {
|
function dateTimeUTC(utc) {
|
||||||
const timeNow = new Date()
|
const timeNow = new Date();
|
||||||
const utcOffset = timeNow.getTimezoneOffset()
|
const utcOffset = timeNow.getTimezoneOffset();
|
||||||
timeNow.setMinutes(timeNow.getMinutes() + utcOffset)
|
timeNow.setMinutes(timeNow.getMinutes() + utcOffset);
|
||||||
const enteredOffset = parseFloat(utc) * 60
|
const enteredOffset = parseFloat(utc)*60;
|
||||||
timeNow.setMinutes(timeNow.getMinutes() + enteredOffset)
|
timeNow.setMinutes(timeNow.getMinutes() + enteredOffset);
|
||||||
return showDateTime(timeNow)
|
return showDateTime(timeNow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,14 +21,13 @@ function dateTimeUTC (utc) {
|
|||||||
* @examples dateTimeUTC('0') → dateTimeUTC vous renvoie l'exécution de showDateTime
|
* @examples dateTimeUTC('0') → dateTimeUTC vous renvoie l'exécution de showDateTime
|
||||||
*/
|
*/
|
||||||
function showDateTime(timeNow) {
|
function showDateTime(timeNow) {
|
||||||
const year = timeNow.getFullYear()
|
const year = timeNow.getFullYear();
|
||||||
const month = ('0' + (timeNow.getMonth() + 1)).slice(-2)
|
const month = ('0'+(timeNow.getMonth()+1)).slice(-2);
|
||||||
const day = ('0' + timeNow.getDate()).slice(-2)
|
const day = ('0'+timeNow.getDate()).slice(-2);
|
||||||
const hour = ('0' + timeNow.getHours()).slice(-2)
|
const hour = ('0'+timeNow.getHours()).slice(-2);
|
||||||
const minute = ('0' + timeNow.getMinutes()).slice(-2)
|
const minute = ('0'+timeNow.getMinutes()).slice(-2);
|
||||||
const second = ('0' + timeNow.getSeconds()).slice(-2)
|
const second = ('0'+timeNow.getSeconds()).slice(-2);
|
||||||
const showDateTimeValue =
|
const showDateTimeValue = day + "/" + month + "/" + year + " - " + hour + ":" + minute + ":" + second;
|
||||||
day + '/' + month + '/' + year + ' - ' + hour + ':' + minute + ':' + second
|
|
||||||
const objectDateTime = {
|
const objectDateTime = {
|
||||||
year: year,
|
year: year,
|
||||||
month: month,
|
month: month,
|
||||||
@ -37,8 +36,8 @@ function showDateTime (timeNow) {
|
|||||||
minute: minute,
|
minute: minute,
|
||||||
second: second,
|
second: second,
|
||||||
showDateTimeValue: showDateTimeValue
|
showDateTimeValue: showDateTimeValue
|
||||||
}
|
};
|
||||||
return objectDateTime
|
return objectDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = dateTimeUTC
|
module.exports = dateTimeUTC;
|
@ -5,10 +5,10 @@
|
|||||||
* @returns {String} - Le nombre formaté
|
* @returns {String} - Le nombre formaté
|
||||||
* @examples formatNumberResult(76120) → '76 120'
|
* @examples formatNumberResult(76120) → '76 120'
|
||||||
*/
|
*/
|
||||||
function formatNumberResult (number, separator = '.') {
|
function formatNumberResult(number, separator = ".") {
|
||||||
const parts = number.toString().split(separator)
|
let parts = number.toString().split(separator);
|
||||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ' ')
|
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, " ");
|
||||||
return parts.join(separator)
|
return parts.join(separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = formatNumberResult
|
module.exports = formatNumberResult;
|
Before Width: | Height: | Size: 9.2 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 16 KiB |
@ -1,15 +1,9 @@
|
|||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const { DATABASE } = require('../config/config')
|
const { DATABASE } = require('../config/config');
|
||||||
|
|
||||||
const sequelize = new Sequelize(
|
const sequelize = new Sequelize(DATABASE.name, DATABASE.user, DATABASE.password, {
|
||||||
DATABASE.name,
|
|
||||||
DATABASE.user,
|
|
||||||
DATABASE.password,
|
|
||||||
{
|
|
||||||
dialect: 'mysql',
|
dialect: 'mysql',
|
||||||
host: DATABASE.host,
|
host: DATABASE.host
|
||||||
port: DATABASE.port
|
});
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
module.exports = sequelize
|
module.exports = sequelize;
|
@ -1,19 +1,19 @@
|
|||||||
const fs = require('fs')
|
const fs = require("fs");
|
||||||
const path = require('path')
|
const path = require("path");
|
||||||
|
|
||||||
function deleteFilesNameStartWith(pattern, dirPath, callback) {
|
function deleteFilesNameStartWith(pattern, dirPath, callback) {
|
||||||
fs.readdir(path.resolve(dirPath), (_error, fileNames) => {
|
fs.readdir(path.resolve(dirPath), (_error, fileNames) => {
|
||||||
for (const name of fileNames) {
|
for (const name of fileNames) {
|
||||||
const splitedName = name.split('.')
|
const splitedName = name.split('.');
|
||||||
if (splitedName.length === 2) {
|
if (splitedName.length === 2) {
|
||||||
const fileName = splitedName[0]
|
const fileName = splitedName[0];
|
||||||
if (fileName === pattern && name !== 'default.png') {
|
if (fileName === pattern && name !== 'default.png') {
|
||||||
return fs.unlink(path.join(dirPath, name), callback)
|
return fs.unlink(path.join(dirPath, name), callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return callback()
|
return callback();
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = deleteFilesNameStartWith
|
module.exports = deleteFilesNameStartWith;
|
@ -1,7 +1,7 @@
|
|||||||
function errorHandling(next, { statusCode, message }) {
|
function errorHandling(next, { statusCode, message }) {
|
||||||
const error = new Error(message)
|
const error = new Error(message);
|
||||||
error.statusCode = statusCode
|
error.statusCode = statusCode;
|
||||||
next(error)
|
next(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = errorHandling
|
module.exports = errorHandling;
|
@ -1,10 +1,10 @@
|
|||||||
const errorHandling = require('../utils/errorHandling')
|
const errorHandling = require('../utils/errorHandling');
|
||||||
const { serverError } = require('../config/errors')
|
const { serverError } = require('../config/errors');
|
||||||
const helperQueryNumber = require('../utils/helperQueryNumber')
|
const helperQueryNumber = require('../utils/helperQueryNumber');
|
||||||
|
|
||||||
const DEFAULT_OPTIONS = {
|
const DEFAULT_OPTIONS = {
|
||||||
order: [['createdAt', 'DESC']]
|
order: [['createdAt', 'DESC']]
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Permet de faire un système de pagination sur un model Sequelize
|
* @description Permet de faire un système de pagination sur un model Sequelize
|
||||||
@ -12,27 +12,23 @@ const DEFAULT_OPTIONS = {
|
|||||||
* @param {*} Model Model Sequelize
|
* @param {*} Model Model Sequelize
|
||||||
* @param {Object} options Options avec clause where etc.
|
* @param {Object} options Options avec clause where etc.
|
||||||
*/
|
*/
|
||||||
async function getPagesHelper (
|
async function getPagesHelper({ req, res, next }, Model, options = DEFAULT_OPTIONS) {
|
||||||
{ req, res, next },
|
const page = helperQueryNumber(req.query.page, 1);
|
||||||
Model,
|
const limit = helperQueryNumber(req.query.limit, 10);
|
||||||
options = DEFAULT_OPTIONS
|
const offset = (page - 1) * limit;
|
||||||
) {
|
|
||||||
const page = helperQueryNumber(req.query.page, 1)
|
|
||||||
const limit = helperQueryNumber(req.query.limit, 10)
|
|
||||||
const offset = (page - 1) * limit
|
|
||||||
try {
|
try {
|
||||||
const result = await Model.findAndCountAll({
|
const result = await Model.findAndCountAll({
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
...options
|
...options
|
||||||
})
|
});
|
||||||
const { count, rows } = result
|
const { count, rows } = result;
|
||||||
const hasMore = page * limit < count
|
const hasMore = (page * limit) < count;
|
||||||
return res.status(200).json({ totalItems: count, hasMore, rows })
|
return res.status(200).json({ totalItems: count, hasMore, rows });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = getPagesHelper
|
module.exports = getPagesHelper;
|
@ -1,6 +1,6 @@
|
|||||||
function helperQueryNumber(value, defaultValue) {
|
function helperQueryNumber(value, defaultValue) {
|
||||||
if (value && !isNaN(value)) return parseInt(value)
|
if (value && !isNaN(value)) return parseInt(value);
|
||||||
return defaultValue
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = helperQueryNumber
|
module.exports = helperQueryNumber;
|
@ -1,424 +1,320 @@
|
|||||||
const path = require('path')
|
const path = require('path');
|
||||||
const fs = require('fs')
|
const fs = require('fs');
|
||||||
const { validationResult } = require('express-validator')
|
const { validationResult } = require('express-validator');
|
||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const { serverError } = require('../assets/config/errors')
|
const { serverError } = require('../assets/config/errors');
|
||||||
const Functions = require('../models/functions')
|
const Functions = require('../models/functions');
|
||||||
const Categories = require('../models/categories')
|
const Categories = require('../models/categories');
|
||||||
const Quotes = require('../models/quotes')
|
const Quotes = require('../models/quotes');
|
||||||
const Users = require('../models/users')
|
const Users = require('../models/users');
|
||||||
const helperQueryNumber = require('../assets/utils/helperQueryNumber')
|
const helperQueryNumber = require('../assets/utils/helperQueryNumber');
|
||||||
const getPagesHelper = require('../assets/utils/getPagesHelper')
|
const getPagesHelper = require('../assets/utils/getPagesHelper');
|
||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const deleteFilesNameStartWith = require('../assets/utils/deleteFilesNameStartWith')
|
const deleteFilesNameStartWith = require('../assets/utils/deleteFilesNameStartWith');
|
||||||
const { EMAIL_INFO, FRONT_END_HOST } = require('../assets/config/config')
|
const { EMAIL_INFO, FRONT_END_HOST } = require('../assets/config/config');
|
||||||
const transporter = require('../assets/config/transporter')
|
const transporter = require('../assets/config/transporter');
|
||||||
const { emailQuoteTemplate } = require('../assets/config/emails')
|
const { emailQuoteTemplate } = require('../assets/config/emails');
|
||||||
|
|
||||||
const handleEditFunction = async (
|
const handleEditFunction = async (res, resultFunction, { title, slug, description, type, categorieId, isOnline }, imageName = false) => {
|
||||||
res,
|
resultFunction.title = title;
|
||||||
resultFunction,
|
resultFunction.slug = slug;
|
||||||
{ title, slug, description, type, categorieId, isOnline },
|
resultFunction.description = description;
|
||||||
imageName = false
|
resultFunction.type = type;
|
||||||
) => {
|
resultFunction.categorieId = categorieId;
|
||||||
resultFunction.title = title
|
resultFunction.isOnline = isOnline;
|
||||||
resultFunction.slug = slug
|
|
||||||
resultFunction.description = description
|
|
||||||
resultFunction.type = type
|
|
||||||
resultFunction.categorieId = categorieId
|
|
||||||
resultFunction.isOnline = isOnline
|
|
||||||
if (imageName) {
|
if (imageName) {
|
||||||
resultFunction.image = `/images/functions/${imageName}`
|
resultFunction.image = `/images/functions/${imageName}`;
|
||||||
}
|
}
|
||||||
const result = await resultFunction.save()
|
const result = await resultFunction.save();
|
||||||
res.status(200).json({ message: 'La fonction a bien été modifié!', result })
|
res.status(200).json({ message: "La fonction a bien été modifié!", result });
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getFunctions = async (req, res, next) => {
|
exports.getFunctions = async (req, res, next) => {
|
||||||
const categoryId = helperQueryNumber(req.query.categoryId, 0)
|
const categoryId = helperQueryNumber(req.query.categoryId, 0);
|
||||||
let search = req.query.search
|
let search = req.query.search;
|
||||||
try {
|
try { search = search.toLowerCase(); } catch {};
|
||||||
search = search.toLowerCase()
|
|
||||||
} catch {}
|
|
||||||
const options = {
|
const options = {
|
||||||
where: {
|
where: {
|
||||||
// Trie par catégorie
|
// Trie par catégorie
|
||||||
...(categoryId !== 0 && { categorieId: categoryId }),
|
... (categoryId !== 0) && { categorieId: categoryId },
|
||||||
// Recherche
|
// Recherche
|
||||||
...(search != null && {
|
... (search != undefined) && {
|
||||||
[Sequelize.Op.or]: [
|
[Sequelize.Op.or]: [
|
||||||
{
|
{ title: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('title')), 'LIKE', `%${search}%`) },
|
||||||
title: Sequelize.where(
|
{ slug: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('slug')), 'LIKE', `%${search}%`) },
|
||||||
Sequelize.fn('LOWER', Sequelize.col('title')),
|
{ description: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('description')), 'LIKE', `%${search}%`) }
|
||||||
'LIKE',
|
|
||||||
`%${search}%`
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: Sequelize.where(
|
|
||||||
Sequelize.fn('LOWER', Sequelize.col('slug')),
|
|
||||||
'LIKE',
|
|
||||||
`%${search}%`
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: Sequelize.where(
|
|
||||||
Sequelize.fn('LOWER', Sequelize.col('description')),
|
|
||||||
'LIKE',
|
|
||||||
`%${search}%`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
})
|
}
|
||||||
},
|
},
|
||||||
include: [{ model: Categories, attributes: ['name', 'color'] }],
|
include: [
|
||||||
|
{ model: Categories, attributes: ["name", "color"] }
|
||||||
|
],
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ['updatedAt', 'utilizationForm', 'article', 'isOnline']
|
exclude: ["updatedAt", "utilizationForm", "article", "isOnline"]
|
||||||
},
|
},
|
||||||
order: [['createdAt', 'DESC']]
|
order: [['createdAt', 'DESC']]
|
||||||
}
|
};
|
||||||
return await getPagesHelper({ req, res, next }, Functions, options)
|
return await getPagesHelper({ req, res, next }, Functions, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getFunctionBySlug = (req, res, next) => {
|
exports.getFunctionBySlug = (req, res, next) => {
|
||||||
const { slug } = req.params
|
const { slug } = req.params;
|
||||||
Functions.findOne({
|
Functions.findOne({
|
||||||
where: { slug },
|
where: { slug },
|
||||||
include: [{ model: Categories, attributes: ['name', 'color'] }]
|
include: [
|
||||||
|
{ model: Categories, attributes: ["name", "color"] }
|
||||||
|
]
|
||||||
})
|
})
|
||||||
.then(result => {
|
.then((result) => {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try { result.utilizationForm = JSON.parse(result.utilizationForm); } catch {}
|
||||||
result.utilizationForm = JSON.parse(result.utilizationForm)
|
return res.status(200).json(result);
|
||||||
} catch {}
|
|
||||||
return res.status(200).json(result)
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error)
|
|
||||||
return errorHandling(next, serverError)
|
|
||||||
})
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
return errorHandling(next, serverError);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.postFunction = (req, res, next) => {
|
exports.postFunction = (req, res, next) => {
|
||||||
const { title, slug, description, type, categorieId } = req.body
|
const { title, slug, description, type, categorieId } = req.body;
|
||||||
const image = req.files.image
|
const image = req.files.image;
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
|
||||||
message: errors.array()[0].msg,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (
|
if (!image || image.truncated && (
|
||||||
(!image || image.truncated) &&
|
image.mimetype !== 'image/png' ||
|
||||||
(image.mimetype !== 'image/png' ||
|
|
||||||
image.mimetype !== 'image/jpg' ||
|
image.mimetype !== 'image/jpg' ||
|
||||||
image.mimetype !== 'image/jpeg')
|
image.mimetype !== 'image/jpeg'
|
||||||
) {
|
)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message:"La fonction doit avoir une image valide.", statusCode: 400 });
|
||||||
message: 'La fonction doit avoir une image valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const splitedImageName = image.name.split('.')
|
const splitedImageName = image.name.split('.');
|
||||||
if (splitedImageName.length !== 2) return errorHandling(next, serverError)
|
if (splitedImageName.length !== 2) return errorHandling(next, serverError);
|
||||||
const imageName = slug + '.' + splitedImageName[1]
|
const imageName = slug + '.' + splitedImageName[1];
|
||||||
image.mv(
|
image.mv(path.join(__dirname, '..', 'assets', 'images', 'functions') + '/' + imageName, async (error) => {
|
||||||
path.join(__dirname, '..', 'assets', 'images', 'functions') +
|
if (error) return errorHandling(next, serverError);
|
||||||
'/' +
|
|
||||||
imageName,
|
|
||||||
async error => {
|
|
||||||
if (error) return errorHandling(next, serverError)
|
|
||||||
try {
|
try {
|
||||||
const result = await Functions.create({
|
const result = await Functions.create({ title, slug, description, type, categorieId, image: `/images/functions/${imageName}` });
|
||||||
title,
|
return res.status(201).json({ message: "La fonction a été correctement ajouté!", result });
|
||||||
slug,
|
|
||||||
description,
|
|
||||||
type,
|
|
||||||
categorieId,
|
|
||||||
image: `/images/functions/${imageName}`
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
.status(201)
|
|
||||||
.json({ message: 'La fonction a été correctement ajouté!', result })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.putFunction = async (req, res, next) => {
|
exports.putFunction = async (req, res, next) => {
|
||||||
const { id } = req.params
|
const { id } = req.params;
|
||||||
const { title, slug, description, type, categorieId, isOnline } = req.body
|
const { title, slug, description, type, categorieId, isOnline } = req.body;
|
||||||
const image = req.files.image
|
const image = req.files.image;
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
|
||||||
message: errors.array()[0].msg,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Vérifie si la fonction existe
|
// Vérifie si la fonction existe
|
||||||
const resultFunction = await Functions.findOne({ where: { id } })
|
const resultFunction = await Functions.findOne({ where: { id } });
|
||||||
if (!resultFunction) {
|
if (!resultFunction) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vérifie si le slug existe déjà
|
// Vérifie si le slug existe déjà
|
||||||
const FunctionSlug = await Functions.findOne({ where: { slug } })
|
const FunctionSlug = await Functions.findOne({ where: { slug } });
|
||||||
if (!FunctionSlug && FunctionSlug.id !== resultFunction.id) {
|
if (!FunctionSlug && FunctionSlug.id != resultFunction.id) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Le slug existe déjà...", statusCode: 404 });
|
||||||
message: 'Le slug existe déjà...',
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sauvegarde de la fonction
|
// Sauvegarde de la fonction
|
||||||
if (image != null) {
|
if (image != undefined) {
|
||||||
if (
|
if (image.truncated && (
|
||||||
image.truncated &&
|
image.mimetype !== 'image/png' ||
|
||||||
(image.mimetype !== 'image/png' ||
|
|
||||||
image.mimetype !== 'image/jpg' ||
|
image.mimetype !== 'image/jpg' ||
|
||||||
image.mimetype !== 'image/jpeg')
|
image.mimetype !== 'image/jpeg'
|
||||||
) {
|
)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message:"La fonction doit avoir une image valide.", statusCode: 400 });
|
||||||
message: 'La fonction doit avoir une image valide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const splitedImageName = image.name.split('.')
|
const splitedImageName = image.name.split('.');
|
||||||
if (splitedImageName.length !== 2) return errorHandling(next, serverError)
|
if (splitedImageName.length !== 2) return errorHandling(next, serverError);
|
||||||
const imageName = slug + '.' + splitedImageName[1]
|
const imageName = slug + '.' + splitedImageName[1];
|
||||||
// Supprime les anciennes images
|
// Supprime les anciennes images
|
||||||
const functionPath = path.join(
|
const functionPath = path.join(__dirname, '..', 'assets', 'images', 'functions');
|
||||||
__dirname,
|
|
||||||
'..',
|
|
||||||
'assets',
|
|
||||||
'images',
|
|
||||||
'functions'
|
|
||||||
)
|
|
||||||
deleteFilesNameStartWith(slug, functionPath, () => {
|
deleteFilesNameStartWith(slug, functionPath, () => {
|
||||||
image.mv(path.join(functionPath, imageName), async error => {
|
image.mv(path.join(functionPath, imageName), async (error) => {
|
||||||
if (error) return errorHandling(next, serverError)
|
if (error) return errorHandling(next, serverError);
|
||||||
return await handleEditFunction(
|
return await handleEditFunction(res, resultFunction, { title, slug, description, type, categorieId, isOnline }, imageName);
|
||||||
res,
|
});
|
||||||
resultFunction,
|
});
|
||||||
{ title, slug, description, type, categorieId, isOnline },
|
|
||||||
imageName
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
return await handleEditFunction(res, resultFunction, {
|
return await handleEditFunction(res, resultFunction, { title, slug, description, type, categorieId, isOnline });
|
||||||
title,
|
|
||||||
slug,
|
|
||||||
description,
|
|
||||||
type,
|
|
||||||
categorieId,
|
|
||||||
isOnline
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.putFunctionArticle = async (req, res, next) => {
|
exports.putFunctionArticle = async (req, res, next) => {
|
||||||
const { id } = req.params
|
const { id } = req.params;
|
||||||
const { article } = req.body
|
const { article } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Vérifie si la fonction existe
|
// Vérifie si la fonction existe
|
||||||
const resultFunction = await Functions.findOne({ where: { id } })
|
const resultFunction = await Functions.findOne({ where: { id } });
|
||||||
if (!resultFunction) {
|
if (!resultFunction) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
resultFunction.article = article
|
resultFunction.article = article;
|
||||||
const result = await resultFunction.save()
|
const result = await resultFunction.save();
|
||||||
return res.status(200).json(result)
|
return res.status(200).json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.putFunctionForm = async (req, res, next) => {
|
exports.putFunctionForm = async (req, res, next) => {
|
||||||
const { id } = req.params
|
const { id } = req.params;
|
||||||
const { form } = req.body
|
const { form } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Vérifie si la fonction existe
|
// Vérifie si la fonction existe
|
||||||
const resultFunction = await Functions.findOne({ where: { id } })
|
const resultFunction = await Functions.findOne({ where: { id } });
|
||||||
if (!resultFunction) {
|
if (!resultFunction) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
resultFunction.utilizationForm = JSON.stringify(form)
|
resultFunction.utilizationForm = JSON.stringify(form);
|
||||||
const result = await resultFunction.save()
|
const result = await resultFunction.save();
|
||||||
return res.status(200).json(result)
|
return res.status(200).json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.deleteFunction = async (req, res, next) => {
|
exports.deleteFunction = async (req, res, next) => {
|
||||||
const { id } = req.params
|
const { id } = req.params;
|
||||||
try {
|
try {
|
||||||
const result = await Functions.findOne({ where: { id } })
|
const result = await Functions.findOne({ where: { id } });
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (result.image !== '/images/functions/default.png') {
|
if (result.image !== "/images/functions/default.png") {
|
||||||
const filePath = path.join(__dirname, '..', 'assets', result.image)
|
const filePath = path.join(__dirname, '..', 'assets', result.image);
|
||||||
fs.unlinkSync(filePath) // supprime le fichier
|
fs.unlinkSync(filePath); // supprime le fichier
|
||||||
}
|
}
|
||||||
await result.destroy()
|
await result.destroy();
|
||||||
res
|
res.status(200).json({ message: "La fonction a été correctement supprimé!"});
|
||||||
.status(200)
|
|
||||||
.json({ message: 'La fonction a été correctement supprimé!' })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.postCategory = async (req, res, next) => {
|
exports.postCategory = async (req, res, next) => {
|
||||||
const { name, color } = req.body
|
const { name, color } = req.body;
|
||||||
if (!(name && color)) {
|
if (!(name && color)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La catégorie doit avoir un nom et une couleur." });
|
||||||
message: 'La catégorie doit avoir un nom et une couleur.'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const result = await Categories.create({ name, color })
|
const result = await Categories.create({ name, color });
|
||||||
return res
|
return res.status(201).json({ message: "La catégorie a bien été crée!", result });
|
||||||
.status(201)
|
|
||||||
.json({ message: 'La catégorie a bien été crée!', result })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.putCategory = async (req, res, next) => {
|
exports.putCategory = async (req, res, next) => {
|
||||||
const { name, color } = req.body
|
const { name, color } = req.body;
|
||||||
const { id } = req.params
|
const { id } = req.params;
|
||||||
if (!(name && color && id)) {
|
if (!(name && color && id)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La catégorie doit avoir un nom, une couleur et un id." });
|
||||||
message: 'La catégorie doit avoir un nom, une couleur et un id.'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const category = await Categories.findOne({ where: { id } })
|
const category = await Categories.findOne({ where: { id } });
|
||||||
if (!category) {
|
if (!category) {
|
||||||
return errorHandling(next, { message: "La catégorie n'existe pas." })
|
return errorHandling(next, { message: "La catégorie n'existe pas." });
|
||||||
}
|
}
|
||||||
category.name = name
|
category.name = name;
|
||||||
category.color = color
|
category.color = color;
|
||||||
const result = await category.save()
|
const result = await category.save();
|
||||||
return res
|
return res.status(200).json({ message: "La catégorie a bien été modifiée!", result });
|
||||||
.status(200)
|
|
||||||
.json({ message: 'La catégorie a bien été modifiée!', result })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.deleteCategory = async (req, res, next) => {
|
exports.deleteCategory = async (req, res, next) => {
|
||||||
const { id } = req.params
|
const { id } = req.params;
|
||||||
try {
|
try {
|
||||||
const category = await Categories.findOne({ where: { id } })
|
const category = await Categories.findOne({ where: { id } });
|
||||||
if (!category) {
|
if (!category) {
|
||||||
return errorHandling(next, { message: "La catégorie n'existe pas." })
|
return errorHandling(next, { message: "La catégorie n'existe pas." });
|
||||||
}
|
}
|
||||||
await category.destroy()
|
await category.destroy();
|
||||||
return res
|
return res.status(200).json({ message: "La catégorie a bien été supprimée!" });
|
||||||
.status(200)
|
|
||||||
.json({ message: 'La catégorie a bien été supprimée!' })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getQuotes = async (req, res, next) => {
|
exports.getQuotes = async (req, res, next) => {
|
||||||
const options = {
|
const options = {
|
||||||
where: {
|
where: {
|
||||||
isValidated: 0
|
isValidated: 0,
|
||||||
},
|
},
|
||||||
include: [{ model: Users, attributes: ['name', 'logo'] }],
|
include: [
|
||||||
|
{ model: Users, attributes: ["name", "logo"] }
|
||||||
|
],
|
||||||
order: [['createdAt', 'DESC']]
|
order: [['createdAt', 'DESC']]
|
||||||
}
|
};
|
||||||
return await getPagesHelper({ req, res, next }, Quotes, options)
|
return await getPagesHelper({ req, res, next }, Quotes, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.putQuote = async (req, res, next) => {
|
exports.putQuote = async (req, res, next) => {
|
||||||
const { id } = req.params
|
const { id } = req.params;
|
||||||
const { isValid } = req.body
|
const { isValid } = req.body;
|
||||||
try {
|
try {
|
||||||
if (typeof isValid !== 'boolean') {
|
if (typeof isValid !== 'boolean') {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "isValid doit être un booléen.", statusCode: 400 });
|
||||||
message: 'isValid doit être un booléen.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const quote = await Quotes.findOne({
|
const quote = await Quotes.findOne({
|
||||||
where: {
|
where: {
|
||||||
id,
|
id,
|
||||||
isValidated: 0
|
isValidated: 0
|
||||||
},
|
},
|
||||||
include: [{ model: Users, attributes: ['name', 'email'] }]
|
include: [
|
||||||
})
|
{ model: Users, attributes: ["name", "email"] }
|
||||||
|
]
|
||||||
|
});
|
||||||
if (!quote) {
|
if (!quote) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La citation n'existe pas (ou est déjà validé).", statusCode: 404 });
|
||||||
message: "La citation n'existe pas (ou est déjà validé).",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await transporter.sendMail({
|
await transporter.sendMail({
|
||||||
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
|
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
|
||||||
to: quote.user.email,
|
to: quote.user.email,
|
||||||
subject: 'FunctionProject - Citation proposée',
|
subject: "FunctionProject - Citation proposée",
|
||||||
html: emailQuoteTemplate(isValid, quote, FRONT_END_HOST)
|
html: emailQuoteTemplate(isValid, quote, FRONT_END_HOST)
|
||||||
})
|
});
|
||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
quote.isValidated = true
|
quote.isValidated = true;
|
||||||
await quote.save()
|
await quote.save();
|
||||||
return res
|
return res.status(200).json({ message: "La citation a bien été validée!" });
|
||||||
.status(200)
|
|
||||||
.json({ message: 'La citation a bien été validée!' })
|
|
||||||
} else {
|
} else {
|
||||||
await quote.destroy()
|
await quote.destroy();
|
||||||
return res
|
return res.status(200).json({ imessage: "La citation a bien été supprimée!" });
|
||||||
.status(200)
|
|
||||||
.json({ imessage: 'La citation a bien été supprimée!' })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const Categories = require('../models/categories')
|
const Categories = require('../models/categories');
|
||||||
const { serverError } = require('../assets/config/errors')
|
const { serverError } = require('../assets/config/errors');
|
||||||
|
|
||||||
exports.getCategories = (_req, res, next) => {
|
exports.getCategories = (_req, res, next) => {
|
||||||
Categories.findAll()
|
Categories.findAll()
|
||||||
.then(result => {
|
.then((result) => {
|
||||||
res.status(200).json(result)
|
res.status(200).json(result);
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error)
|
|
||||||
return errorHandling(next, serverError)
|
|
||||||
})
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
return errorHandling(next, serverError);
|
||||||
|
});
|
||||||
}
|
}
|
@ -1,99 +1,72 @@
|
|||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const Comments = require('../models/comments')
|
const Comments = require('../models/comments');
|
||||||
const Users = require('../models/users')
|
const Users = require('../models/users');
|
||||||
const Functions = require('../models/functions')
|
const Functions = require('../models/functions');
|
||||||
const getPagesHelper = require('../assets/utils/getPagesHelper')
|
const getPagesHelper = require('../assets/utils/getPagesHelper');
|
||||||
const { serverError } = require('../assets/config/errors')
|
const { serverError } = require('../assets/config/errors');
|
||||||
|
|
||||||
exports.getCommentsByFunctionId = async (req, res, next) => {
|
exports.getCommentsByFunctionId = async (req, res, next) => {
|
||||||
const { functionId } = req.params
|
const { functionId } = req.params;
|
||||||
const options = {
|
const options = {
|
||||||
where: { functionId },
|
where: { functionId },
|
||||||
include: [{ model: Users, attributes: ['name', 'logo'] }],
|
include: [
|
||||||
|
{ model: Users, attributes: ["name", "logo"] }
|
||||||
|
],
|
||||||
order: [['createdAt', 'DESC']]
|
order: [['createdAt', 'DESC']]
|
||||||
}
|
};
|
||||||
return await getPagesHelper({ req, res, next }, Comments, options)
|
return await getPagesHelper({ req, res, next }, Comments, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.postCommentsByFunctionId = async (req, res, next) => {
|
exports.postCommentsByFunctionId = async (req, res, next) => {
|
||||||
const { functionId } = req.params
|
const { functionId } = req.params;
|
||||||
const { message } = req.body
|
const { message } = req.body;
|
||||||
try {
|
try {
|
||||||
const resultFunction = await Functions.findOne({
|
const resultFunction = await Functions.findOne({ where: { id: functionId } });
|
||||||
where: { id: functionId }
|
|
||||||
})
|
|
||||||
if (!resultFunction) {
|
if (!resultFunction) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (!message) {
|
if (!message) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous ne pouvez pas poster de commentaire vide.", statusCode: 400 });
|
||||||
message: 'Vous ne pouvez pas poster de commentaire vide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const comment = await Comments.create({
|
const comment = await Comments.create({ message, userId: req.userId, functionId });
|
||||||
message,
|
return res.status(201).json(comment);
|
||||||
userId: req.userId,
|
|
||||||
functionId
|
|
||||||
})
|
|
||||||
return res.status(201).json(comment)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.deleteCommentById = async (req, res, next) => {
|
exports.deleteCommentById = async (req, res, next) => {
|
||||||
const { commentId } = req.params
|
const { commentId } = req.params;
|
||||||
try {
|
try {
|
||||||
const comment = await Comments.findOne({
|
const comment = await Comments.findOne({ where: { userId: req.userId, id: parseInt(commentId) } });
|
||||||
where: { userId: req.userId, id: parseInt(commentId) }
|
|
||||||
})
|
|
||||||
if (!comment) {
|
if (!comment) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Le commentaire n'existe pas.", statusCode: 404 });
|
||||||
message: "Le commentaire n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
await comment.destroy()
|
await comment.destroy();
|
||||||
return res
|
return res.status(200).json({ message: "Le commentaire a bien été supprimé." });
|
||||||
.status(200)
|
|
||||||
.json({ message: 'Le commentaire a bien été supprimé.' })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.putCommentsById = async (req, res, next) => {
|
exports.putCommentsById = async (req, res, next) => {
|
||||||
const { commentId } = req.params
|
const { commentId } = req.params;
|
||||||
const { message } = req.body
|
const { message } = req.body;
|
||||||
if (!message) {
|
if (!message) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous ne pouvez pas poster de commentaire vide.", statusCode: 400 });
|
||||||
message: 'Vous ne pouvez pas poster de commentaire vide.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const comment = await Comments.findOne({
|
const comment = await Comments.findOne({ where: { userId: req.userId, id: parseInt(commentId) } });
|
||||||
where: { userId: req.userId, id: parseInt(commentId) }
|
|
||||||
})
|
|
||||||
if (!comment) {
|
if (!comment) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Le commentaire n'existe pas.", statusCode: 404 });
|
||||||
message: "Le commentaire n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
comment.message = message
|
comment.message = message;
|
||||||
await comment.save()
|
await comment.save();
|
||||||
return res
|
return res.status(200).json({ message: "Le commentaire a bien été modifié." });
|
||||||
.status(200)
|
|
||||||
.json({ message: 'Le commentaire a bien été modifié.' })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,92 +1,74 @@
|
|||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const { serverError } = require('../assets/config/errors')
|
const { serverError } = require('../assets/config/errors');
|
||||||
const Favorites = require('../models/favorites')
|
const Favorites = require('../models/favorites');
|
||||||
const Functions = require('../models/functions')
|
const Functions = require('../models/functions');
|
||||||
|
|
||||||
exports.getFavoriteByFunctionId = async (req, res, next) => {
|
exports.getFavoriteByFunctionId = async (req, res, next) => {
|
||||||
const { functionId } = req.params
|
const { functionId } = req.params;
|
||||||
const { userId } = req
|
const { userId } = req;
|
||||||
try {
|
try {
|
||||||
const favorite = await Favorites.findOne({
|
const favorite = await Favorites.findOne({
|
||||||
where: {
|
where: {
|
||||||
userId,
|
userId,
|
||||||
functionId
|
functionId
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
if (!favorite) {
|
if (!favorite) {
|
||||||
return res.status(200).json({ isFavorite: false })
|
return res.status(200).json({ isFavorite: false });
|
||||||
}
|
}
|
||||||
return res.status(200).json({ isFavorite: true })
|
return res.status(200).json({ isFavorite: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.postFavoriteByFunctionId = async (req, res, next) => {
|
exports.postFavoriteByFunctionId = async (req, res, next) => {
|
||||||
const { functionId } = req.params
|
const { functionId } = req.params;
|
||||||
const { userId } = req
|
const { userId } = req;
|
||||||
try {
|
try {
|
||||||
const resultFunction = await Functions.findOne({
|
const resultFunction = await Functions.findOne({ where: { id: functionId } });
|
||||||
where: { id: functionId }
|
|
||||||
})
|
|
||||||
if (!resultFunction) {
|
if (!resultFunction) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const favorite = await Favorites.findOne({
|
const favorite = await Favorites.findOne({
|
||||||
where: {
|
where: {
|
||||||
userId,
|
userId,
|
||||||
functionId
|
functionId
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
if (!favorite) {
|
if (!favorite) {
|
||||||
await Favorites.create({ userId, functionId })
|
await Favorites.create({ userId, functionId });
|
||||||
return res.status(201).json({ result: 'Le favoris a bien été ajouté!' })
|
return res.status(201).json({ result: "Le favoris a bien été ajouté!" });
|
||||||
}
|
}
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction est déjà en favoris.", statusCode: 400 });
|
||||||
message: 'La fonction est déjà en favoris.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.deleteFavoriteByFunctionId = async (req, res, next) => {
|
exports.deleteFavoriteByFunctionId = async (req, res, next) => {
|
||||||
const { functionId } = req.params
|
const { functionId } = req.params;
|
||||||
const { userId } = req
|
const { userId } = req;
|
||||||
try {
|
try {
|
||||||
const resultFunction = await Functions.findOne({
|
const resultFunction = await Functions.findOne({ where: { id: functionId } });
|
||||||
where: { id: functionId }
|
|
||||||
})
|
|
||||||
if (!resultFunction) {
|
if (!resultFunction) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const favorite = await Favorites.findOne({
|
const favorite = await Favorites.findOne({
|
||||||
where: {
|
where: {
|
||||||
userId,
|
userId,
|
||||||
functionId
|
functionId
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
if (!favorite) {
|
if (!favorite) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Le fonction n'est pas en favoris.", statusCode: 400 });
|
||||||
message: "Le fonction n'est pas en favoris.",
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
await favorite.destroy()
|
await favorite.destroy();
|
||||||
return res
|
return res.status(200).json({ message: "Le fonction a bien été supprimé des favoris." });
|
||||||
.status(200)
|
|
||||||
.json({ message: 'Le fonction a bien été supprimé des favoris.' })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,93 +1,69 @@
|
|||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const { serverError } = require('../assets/config/errors')
|
const { serverError } = require('../assets/config/errors');
|
||||||
const Functions = require('../models/functions')
|
const Functions = require('../models/functions');
|
||||||
const Categories = require('../models/categories')
|
const Categories = require('../models/categories');
|
||||||
const functionToExecute = require('../assets/functions/functionObject')
|
const functionToExecute = require('../assets/functions/functionObject');
|
||||||
const helperQueryNumber = require('../assets/utils/helperQueryNumber')
|
const helperQueryNumber = require('../assets/utils/helperQueryNumber');
|
||||||
const getPagesHelper = require('../assets/utils/getPagesHelper')
|
const getPagesHelper = require('../assets/utils/getPagesHelper');
|
||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
|
|
||||||
exports.getFunctions = async (req, res, next) => {
|
exports.getFunctions = async (req, res, next) => {
|
||||||
const categoryId = helperQueryNumber(req.query.categoryId, 0)
|
const categoryId = helperQueryNumber(req.query.categoryId, 0);
|
||||||
let { search } = req.query
|
let { search } = req.query;
|
||||||
try {
|
try { search = search.toLowerCase(); } catch {};
|
||||||
search = search.toLowerCase()
|
|
||||||
} catch {}
|
|
||||||
const options = {
|
const options = {
|
||||||
where: {
|
where: {
|
||||||
isOnline: 1,
|
isOnline: 1,
|
||||||
// Trie par catégorie
|
// Trie par catégorie
|
||||||
...(categoryId !== 0 && { categorieId: categoryId }),
|
... (categoryId !== 0) && { categorieId: categoryId },
|
||||||
// Recherche
|
// Recherche
|
||||||
...(search != null && {
|
... (search != undefined) && {
|
||||||
[Sequelize.Op.or]: [
|
[Sequelize.Op.or]: [
|
||||||
{
|
{ title: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('title')), 'LIKE', `%${search}%`) },
|
||||||
title: Sequelize.where(
|
{ slug: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('slug')), 'LIKE', `%${search}%`) },
|
||||||
Sequelize.fn('LOWER', Sequelize.col('title')),
|
{ description: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('description')), 'LIKE', `%${search}%`) }
|
||||||
'LIKE',
|
|
||||||
`%${search}%`
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: Sequelize.where(
|
|
||||||
Sequelize.fn('LOWER', Sequelize.col('slug')),
|
|
||||||
'LIKE',
|
|
||||||
`%${search}%`
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
description: Sequelize.where(
|
|
||||||
Sequelize.fn('LOWER', Sequelize.col('description')),
|
|
||||||
'LIKE',
|
|
||||||
`%${search}%`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
})
|
}
|
||||||
},
|
},
|
||||||
include: [{ model: Categories, attributes: ['name', 'color'] }],
|
include: [
|
||||||
|
{ model: Categories, attributes: ["name", "color"] }
|
||||||
|
],
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ['updatedAt', 'utilizationForm', 'article', 'isOnline']
|
exclude: ["updatedAt", "utilizationForm", "article", "isOnline"]
|
||||||
},
|
},
|
||||||
order: [['createdAt', 'DESC']]
|
order: [['createdAt', 'DESC']]
|
||||||
}
|
};
|
||||||
return await getPagesHelper({ req, res, next }, Functions, options)
|
return await getPagesHelper({ req, res, next }, Functions, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getFunctionBySlug = (req, res, next) => {
|
exports.getFunctionBySlug = (req, res, next) => {
|
||||||
const { slug } = req.params
|
const { slug } = req.params;
|
||||||
Functions.findOne({
|
Functions.findOne({
|
||||||
where: { slug, isOnline: 1 },
|
where: { slug, isOnline: 1 },
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ['updatedAt', 'isOnline']
|
exclude: ["updatedAt", "isOnline"]
|
||||||
},
|
},
|
||||||
include: [{ model: Categories, attributes: ['name', 'color'] }]
|
include: [
|
||||||
|
{ model: Categories, attributes: ["name", "color"] }
|
||||||
|
]
|
||||||
})
|
})
|
||||||
.then(result => {
|
.then((result) => {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try { result.utilizationForm = JSON.parse(result.utilizationForm); } catch {}
|
||||||
result.utilizationForm = JSON.parse(result.utilizationForm)
|
return res.status(200).json(result);
|
||||||
} catch {}
|
|
||||||
return res.status(200).json(result)
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error)
|
|
||||||
return errorHandling(next, serverError)
|
|
||||||
})
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
return errorHandling(next, serverError);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.executeFunctionBySlug = (req, res, next) => {
|
exports.executeFunctionBySlug = (req, res, next) => {
|
||||||
const functionOutput = functionToExecute(req.params.slug)
|
const functionOutput = functionToExecute(req.params.slug);
|
||||||
if (functionOutput !== undefined) {
|
if (functionOutput !== undefined) {
|
||||||
return functionOutput({ res, next }, req.body)
|
return functionOutput({ res, next }, req.body);
|
||||||
}
|
}
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "La fonction n'existe pas.", statusCode: 404 });
|
||||||
message: "La fonction n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
@ -1,192 +0,0 @@
|
|||||||
const validator = require('validator')
|
|
||||||
const errorHandling = require('../assets/utils/errorHandling')
|
|
||||||
const { requiredFields, serverError } = require('../assets/config/errors')
|
|
||||||
const ShortLinks = require('../models/short_links')
|
|
||||||
const getPagesHelper = require('../assets/utils/getPagesHelper')
|
|
||||||
const Sequelize = require('sequelize')
|
|
||||||
|
|
||||||
const shortLinkBaseURL = 'https://s.divlo.fr'
|
|
||||||
|
|
||||||
exports.getLinks = async (req, res, next) => {
|
|
||||||
const { userId } = req
|
|
||||||
const options = {
|
|
||||||
where: { userId },
|
|
||||||
order: [['createdAt', 'DESC']]
|
|
||||||
}
|
|
||||||
return await getPagesHelper({ req, res, next }, ShortLinks, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.postLink = async (req, res, next) => {
|
|
||||||
const { userId } = req
|
|
||||||
let { url, shortcutName } = req.body
|
|
||||||
|
|
||||||
// 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 ShortLinks.findOne({ where: { url } })
|
|
||||||
if (urlInDatabase) {
|
|
||||||
const urlShort = `${shortLinkBaseURL}/${urlInDatabase.shortcut}`
|
|
||||||
return errorHandling(next, {
|
|
||||||
message: `L'url a déjà été raccourcie... <br/> <br/> <a target="_blank" rel="noopener noreferrer" href="${urlShort}">${urlShort}</a>`,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si le nom du raccourci existe déjà
|
|
||||||
const shortcutInDatabase = await ShortLinks.findOne({
|
|
||||||
where: { shortcut: shortcutName }
|
|
||||||
})
|
|
||||||
if (shortcutInDatabase) {
|
|
||||||
const urlShort = `${shortLinkBaseURL}/${shortcutInDatabase.shortcut}`
|
|
||||||
return errorHandling(next, {
|
|
||||||
message: `Le nom du raccourci a déjà été utilisé... <br/> <br/> <a target="_blank" rel="noopener noreferrer" href="${urlShort}">${urlShort}</a>`,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajout du lien raccourci
|
|
||||||
const result = await ShortLinks.create({
|
|
||||||
url,
|
|
||||||
shortcut: shortcutName,
|
|
||||||
userId
|
|
||||||
})
|
|
||||||
const shortcutLinkResult = `${shortLinkBaseURL}/${result.shortcut}`
|
|
||||||
return res.status(200).json({
|
|
||||||
resultHTML: `URL Raccourcie : <br/> <br/> <a target="_blank" rel="noopener noreferrer" href="${shortcutLinkResult}">${shortcutLinkResult}</a>`,
|
|
||||||
result: shortcutLinkResult,
|
|
||||||
linkDatabase: result
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
return errorHandling(next, serverError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.putLink = async (req, res, next) => {
|
|
||||||
const { id } = req.params
|
|
||||||
const { userId } = req
|
|
||||||
let { url, shortcutName } = req.body
|
|
||||||
|
|
||||||
// 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 par quelqu'un d'autre
|
|
||||||
const urlInDatabase = await ShortLinks.findOne({
|
|
||||||
where: { url, [Sequelize.Op.not]: { userId } }
|
|
||||||
})
|
|
||||||
if (urlInDatabase) {
|
|
||||||
const urlShort = `${shortLinkBaseURL}/${urlInDatabase.shortcut}`
|
|
||||||
return errorHandling(next, {
|
|
||||||
message: `L'url a déjà été raccourcie... <br/> <br/> <a target="_blank" rel="noopener noreferrer" href="${urlShort}">${urlShort}</a>`,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si le nom du raccourci existe déjà par quelqu'un d'autre
|
|
||||||
const shortcutInDatabase = await ShortLinks.findOne({
|
|
||||||
where: { shortcut: shortcutName, [Sequelize.Op.not]: { userId } }
|
|
||||||
})
|
|
||||||
if (shortcutInDatabase) {
|
|
||||||
const urlShort = `${shortLinkBaseURL}/${shortcutInDatabase.shortcut}`
|
|
||||||
return errorHandling(next, {
|
|
||||||
message: `Le nom du raccourci a déjà été utilisé... <br/> <br/> <a target="_blank" rel="noopener noreferrer" href="${urlShort}">${urlShort}</a>`,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modification du lien raccourci
|
|
||||||
const result = await ShortLinks.findOne({
|
|
||||||
where: { id, userId }
|
|
||||||
})
|
|
||||||
console.log(result)
|
|
||||||
if (!result) {
|
|
||||||
return errorHandling(next, {
|
|
||||||
statusCode: 404,
|
|
||||||
message: "Le raccourci n'existe pas..."
|
|
||||||
})
|
|
||||||
}
|
|
||||||
result.url = url
|
|
||||||
result.shortcut = shortcutName
|
|
||||||
const { shortcut } = await result.save()
|
|
||||||
const shortcutLinkResult = `${shortLinkBaseURL}/${shortcut}`
|
|
||||||
return res.status(200).json({
|
|
||||||
resultHTML: `URL Raccourcie : <br/> <br/> <a target="_blank" rel="noopener noreferrer" href="${shortcutLinkResult}">${shortcutLinkResult}</a>`,
|
|
||||||
result: shortcutLinkResult
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
return errorHandling(next, serverError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.deleteLink = async (req, res, next) => {
|
|
||||||
const { id } = req.params
|
|
||||||
const { userId } = req
|
|
||||||
try {
|
|
||||||
const linkResult = await ShortLinks.findOne({
|
|
||||||
where: { id, userId }
|
|
||||||
})
|
|
||||||
if (!linkResult) {
|
|
||||||
return errorHandling(next, {
|
|
||||||
message: "Le lien raccourci n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
|
||||||
await linkResult.destroy()
|
|
||||||
return res.status(200).json({ message: 'La lien a bien été supprimé!' })
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error)
|
|
||||||
return errorHandling(next, serverError)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +1,37 @@
|
|||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const { serverError, requiredFields } = require('../assets/config/errors')
|
const { serverError, requiredFields } = require('../assets/config/errors');
|
||||||
const Quotes = require('../models/quotes')
|
const Quotes = require('../models/quotes');
|
||||||
const Users = require('../models/users')
|
const Users = require('../models/users');
|
||||||
const getPagesHelper = require('../assets/utils/getPagesHelper')
|
const getPagesHelper = require('../assets/utils/getPagesHelper');
|
||||||
|
|
||||||
exports.getQuotes = async (req, res, next) => {
|
exports.getQuotes = async (req, res, next) => {
|
||||||
const options = {
|
const options = {
|
||||||
where: {
|
where: {
|
||||||
isValidated: 1
|
isValidated: 1,
|
||||||
},
|
},
|
||||||
include: [{ model: Users, attributes: ['name', 'logo'] }],
|
include: [
|
||||||
|
{ model: Users, attributes: ["name", "logo"] }
|
||||||
|
],
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ['isValidated']
|
exclude: ["isValidated"]
|
||||||
},
|
},
|
||||||
order: [['createdAt', 'DESC']]
|
order: [['createdAt', 'DESC']]
|
||||||
}
|
};
|
||||||
return await getPagesHelper({ req, res, next }, Quotes, options)
|
return await getPagesHelper({ req, res, next }, Quotes, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.postQuote = (req, res, next) => {
|
exports.postQuote = (req, res, next) => {
|
||||||
const { quote, author } = req.body
|
const { quote, author } = req.body;
|
||||||
// S'il n'y a pas les champs obligatoire
|
// S'il n'y a pas les champs obligatoire
|
||||||
if (!(quote && author)) {
|
if (!(quote && author)) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
Quotes.create({ quote, author, userId: req.userId })
|
Quotes.create({ quote, author, userId: req.userId })
|
||||||
.then(_result => {
|
.then((_result) => {
|
||||||
return res
|
return res.status(200).json({ message: "La citation a bien été ajoutée, elle est en attente de confirmation d'un administrateur." });
|
||||||
.status(200)
|
|
||||||
.json({
|
|
||||||
message:
|
|
||||||
"La citation a bien été ajoutée, elle est en attente de confirmation d'un administrateur."
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error)
|
|
||||||
return errorHandling(next, serverError)
|
|
||||||
})
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
return errorHandling(next, serverError);
|
||||||
|
});
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const { serverError, requiredFields } = require('../assets/config/errors')
|
const { serverError, requiredFields } = require('../assets/config/errors');
|
||||||
const Tasks = require('../models/tasks')
|
const Tasks = require('../models/tasks');
|
||||||
|
|
||||||
exports.getTasks = async (req, res, next) => {
|
exports.getTasks = async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
@ -9,75 +9,60 @@ exports.getTasks = async (req, res, next) => {
|
|||||||
userId: req.userId
|
userId: req.userId
|
||||||
},
|
},
|
||||||
order: [['createdAt', 'DESC']]
|
order: [['createdAt', 'DESC']]
|
||||||
})
|
});
|
||||||
return res.status(200).json(tasks)
|
return res.status(200).json(tasks);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.postTask = async (req, res, next) => {
|
exports.postTask = async (req, res, next) => {
|
||||||
const { task } = req.body
|
const { task } = req.body;
|
||||||
try {
|
try {
|
||||||
if (!task) {
|
if (!task) {
|
||||||
return errorHandling(next, requiredFields)
|
return errorHandling(next, requiredFields);
|
||||||
}
|
}
|
||||||
const taskResult = await Tasks.create({ task, userId: req.userId })
|
const taskResult = await Tasks.create({ task, userId: req.userId });
|
||||||
return res.status(201).json(taskResult)
|
return res.status(201).json(taskResult);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.putTask = async (req, res, next) => {
|
exports.putTask = async (req, res, next) => {
|
||||||
const { id } = req.params
|
const { id } = req.params;
|
||||||
const { isCompleted } = req.body
|
const { isCompleted } = req.body;
|
||||||
try {
|
try {
|
||||||
if (typeof isCompleted !== 'boolean') {
|
if (typeof isCompleted !== 'boolean') {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "isCompleted doit être un booléen.", statusCode: 400 });
|
||||||
message: 'isCompleted doit être un booléen.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const taskResult = await Tasks.findOne({
|
const taskResult = await Tasks.findOne({ where: { id, userId: req.userId } });
|
||||||
where: { id, userId: req.userId }
|
|
||||||
})
|
|
||||||
if (!taskResult) {
|
if (!taskResult) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: `La "tâche à faire" n'existe pas.`, statusCode: 404 });
|
||||||
message: 'La "tâche à faire" n\'existe pas.',
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
taskResult.isCompleted = isCompleted
|
taskResult.isCompleted = isCompleted;
|
||||||
const taskSaved = await taskResult.save()
|
const taskSaved = await taskResult.save();
|
||||||
return res.status(200).json(taskSaved)
|
return res.status(200).json(taskSaved);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.deleteTask = async (req, res, next) => {
|
exports.deleteTask = async (req, res, next) => {
|
||||||
const { id } = req.params
|
const { id } = req.params;
|
||||||
try {
|
try {
|
||||||
const taskResult = await Tasks.findOne({
|
const taskResult = await Tasks.findOne({ where: { id, userId: req.userId } });
|
||||||
where: { id, userId: req.userId }
|
|
||||||
})
|
|
||||||
if (!taskResult) {
|
if (!taskResult) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: `La "tâche à faire" n'existe pas.`, statusCode: 404 });
|
||||||
message: 'La "tâche à faire" n\'existe pas.',
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
await taskResult.destroy()
|
await taskResult.destroy();
|
||||||
return res
|
return res.status(200).json({ message: `La "tâche à faire" a bien été supprimée!` });
|
||||||
.status(200)
|
|
||||||
.json({ message: 'La "tâche à faire" a bien été supprimée!' })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,442 +1,280 @@
|
|||||||
const path = require('path')
|
const path = require('path');
|
||||||
const { validationResult } = require('express-validator')
|
const { validationResult } = require('express-validator');
|
||||||
const bcrypt = require('bcryptjs')
|
const bcrypt = require('bcryptjs');
|
||||||
const jwt = require('jsonwebtoken')
|
const jwt = require('jsonwebtoken');
|
||||||
const ms = require('ms')
|
const ms = require('ms');
|
||||||
const uuid = require('uuid')
|
const uuid = require('uuid');
|
||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const { serverError, generalError } = require('../assets/config/errors')
|
const { serverError, generalError } = require('../assets/config/errors');
|
||||||
const {
|
const { JWT_SECRET, FRONT_END_HOST, EMAIL_INFO, HOST, TOKEN_LIFE } = require('../assets/config/config');
|
||||||
JWT_SECRET,
|
const transporter = require('../assets/config/transporter');
|
||||||
FRONT_END_HOST,
|
const { emailUserTemplate } = require('../assets/config/emails');
|
||||||
EMAIL_INFO,
|
const Users = require('../models/users');
|
||||||
HOST,
|
const Favorites = require('../models/favorites');
|
||||||
TOKEN_LIFE
|
const Functions = require('../models/functions');
|
||||||
} = require('../assets/config/config')
|
const Categories = require('../models/categories');
|
||||||
const transporter = require('../assets/config/transporter')
|
const Comments = require('../models/comments');
|
||||||
const { emailUserTemplate } = require('../assets/config/emails')
|
const Quotes = require('../models/quotes');
|
||||||
const Users = require('../models/users')
|
const deleteFilesNameStartWith = require('../assets/utils/deleteFilesNameStartWith');
|
||||||
const Favorites = require('../models/favorites')
|
const getPagesHelper = require('../assets/utils/getPagesHelper');
|
||||||
const Functions = require('../models/functions')
|
|
||||||
const Categories = require('../models/categories')
|
|
||||||
const Comments = require('../models/comments')
|
|
||||||
const Quotes = require('../models/quotes')
|
|
||||||
const deleteFilesNameStartWith = require('../assets/utils/deleteFilesNameStartWith')
|
|
||||||
const getPagesHelper = require('../assets/utils/getPagesHelper')
|
|
||||||
|
|
||||||
async function handleEditUser (
|
async function handleEditUser(res, { name, email, biography, isPublicEmail }, userId, logoName) {
|
||||||
res,
|
const user = await Users.findOne({ where: { id: userId } });
|
||||||
{ name, email, biography, isPublicEmail },
|
user.name = name;
|
||||||
userId,
|
|
||||||
logoName
|
|
||||||
) {
|
|
||||||
const user = await Users.findOne({ where: { id: userId } })
|
|
||||||
user.name = name
|
|
||||||
if (user.email !== email) {
|
if (user.email !== email) {
|
||||||
const tempToken = uuid.v4()
|
const tempToken = uuid.v4();
|
||||||
user.email = email
|
user.email = email;
|
||||||
user.isConfirmed = false
|
user.isConfirmed = false;
|
||||||
user.tempToken = tempToken
|
user.tempToken = tempToken;
|
||||||
await transporter.sendMail({
|
await transporter.sendMail({
|
||||||
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
|
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
|
||||||
to: email,
|
to: email,
|
||||||
subject: "FunctionProject - Confirmer l'email",
|
subject: "FunctionProject - Confirmer l'email",
|
||||||
html: emailUserTemplate(
|
html: emailUserTemplate("Veuillez confirmer l'email", "Oui, je confirme.", `${HOST}/users/confirm-email/${tempToken}`, "Si vous avez reçu ce message par erreur, il suffit de le supprimer. Votre email ne serez pas confirmé si vous ne cliquez pas sur le lien de confirmation ci-dessus.")
|
||||||
"Veuillez confirmer l'email",
|
});
|
||||||
'Oui, je confirme.',
|
|
||||||
`${HOST}/users/confirm-email/${tempToken}`,
|
|
||||||
'Si vous avez reçu ce message par erreur, il suffit de le supprimer. Votre email ne serez pas confirmé si vous ne cliquez pas sur le lien de confirmation ci-dessus.'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (biography != null) {
|
if (biography != undefined) {
|
||||||
user.biography = biography
|
user.biography = biography;
|
||||||
}
|
}
|
||||||
user.isPublicEmail = isPublicEmail
|
user.isPublicEmail = isPublicEmail;
|
||||||
if (logoName != null && `/images/users/${logoName}` !== user.logo) {
|
if (logoName != undefined && `/images/users/${logoName}` !== user.logo) {
|
||||||
user.logo = `/images/users/${logoName}`
|
user.logo = `/images/users/${logoName}`;
|
||||||
}
|
}
|
||||||
await user.save()
|
await user.save();
|
||||||
return res
|
return res.status(200).json({ id: user.id, name: user.name, email: user.email, biography: user.biography, logo: user.logo, isPublicEmail: user.isPublicEmail, isAdmin: user.isAdmin, createdAt: user.createdAt });
|
||||||
.status(200)
|
|
||||||
.json({
|
|
||||||
id: user.id,
|
|
||||||
name: user.name,
|
|
||||||
email: user.email,
|
|
||||||
biography: user.biography,
|
|
||||||
logo: user.logo,
|
|
||||||
isPublicEmail: user.isPublicEmail,
|
|
||||||
isAdmin: user.isAdmin,
|
|
||||||
createdAt: user.createdAt
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getUsers = async (req, res, next) => {
|
exports.getUsers = async (req, res, next) => {
|
||||||
let { search } = req.query
|
let { search } = req.query;
|
||||||
try {
|
try { search = search.toLowerCase(); } catch {};
|
||||||
search = search.toLowerCase()
|
|
||||||
} catch {}
|
|
||||||
const options = {
|
const options = {
|
||||||
where: {
|
where: {
|
||||||
isConfirmed: true,
|
isConfirmed: true,
|
||||||
// Recherche
|
// Recherche
|
||||||
...(search != null && {
|
...(search != undefined) && {
|
||||||
name: Sequelize.where(
|
name: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), 'LIKE', `%${search}%`)
|
||||||
Sequelize.fn('LOWER', Sequelize.col('name')),
|
}
|
||||||
'LIKE',
|
|
||||||
`%${search}%`
|
|
||||||
)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: [
|
exclude: ["updatedAt", "isAdmin", "isConfirmed", "password", "tempToken", "tempExpirationToken", "isPublicEmail", "email"]
|
||||||
'updatedAt',
|
|
||||||
'isAdmin',
|
|
||||||
'isConfirmed',
|
|
||||||
'password',
|
|
||||||
'tempToken',
|
|
||||||
'tempExpirationToken',
|
|
||||||
'isPublicEmail',
|
|
||||||
'email'
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
order: [['createdAt', 'DESC']]
|
order: [['createdAt', 'DESC']]
|
||||||
}
|
};
|
||||||
return await getPagesHelper({ req, res, next }, Users, options)
|
return await getPagesHelper({ req, res, next }, Users, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.putUser = async (req, res, next) => {
|
exports.putUser = async (req, res, next) => {
|
||||||
const { name, email, biography, isPublicEmail } = req.body
|
const { name, email, biography, isPublicEmail } = req.body;
|
||||||
const logo = req.files.logo
|
const logo = req.files.logo;
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
|
||||||
message: errors.array()[0].msg,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (logo != null) {
|
if (logo != undefined) {
|
||||||
if (
|
if (!logo || logo.truncated && (
|
||||||
(!logo || logo.truncated) &&
|
logo.mimetype !== 'image/png' ||
|
||||||
(logo.mimetype !== 'image/png' ||
|
|
||||||
logo.mimetype !== 'image/jpg' ||
|
logo.mimetype !== 'image/jpg' ||
|
||||||
logo.mimetype !== 'image/jpeg' ||
|
logo.mimetype !== 'image/jpeg' ||
|
||||||
logo.mimetype !== 'image/gif')
|
logo.mimetype !== 'image/gif'
|
||||||
) {
|
)) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message:"Le profil doit avoir une image valide (PNG, JPG, GIF) et moins de 5mo.", statusCode: 400 });
|
||||||
message:
|
|
||||||
'Le profil doit avoir une image valide (PNG, JPG, GIF) et moins de 5mo.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const splitedLogoName = logo.name.split('.')
|
const splitedLogoName = logo.name.split('.');
|
||||||
if (splitedLogoName.length !== 2) return errorHandling(next, serverError)
|
if (splitedLogoName.length !== 2) return errorHandling(next, serverError);
|
||||||
const logoName = name + req.userId + '.' + splitedLogoName[1]
|
const logoName = name + req.userId + '.' + splitedLogoName[1];
|
||||||
// Supprime les anciens logo
|
// Supprime les anciens logo
|
||||||
try {
|
try {
|
||||||
deleteFilesNameStartWith(
|
deleteFilesNameStartWith(`${name + req.userId}`, path.join(__dirname, '..', 'assets', 'images', 'users'), async () => {
|
||||||
`${name + req.userId}`,
|
logo.mv(path.join(__dirname, '..', 'assets', 'images', 'users', logoName), async (error) => {
|
||||||
path.join(__dirname, '..', 'assets', 'images', 'users'),
|
if (error) return errorHandling(next, serverError);
|
||||||
async () => {
|
return await handleEditUser(res, { name, email, biography, isPublicEmail }, req.userId, logoName);
|
||||||
logo.mv(
|
});
|
||||||
path.join(__dirname, '..', 'assets', 'images', 'users', logoName),
|
});
|
||||||
async error => {
|
|
||||||
if (error) return errorHandling(next, serverError)
|
|
||||||
return await handleEditUser(
|
|
||||||
res,
|
|
||||||
{ name, email, biography, isPublicEmail },
|
|
||||||
req.userId,
|
|
||||||
logoName
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
return await handleEditUser(
|
return await handleEditUser(res, { name, email, biography, isPublicEmail }, req.userId, null);
|
||||||
res,
|
|
||||||
{ name, email, biography, isPublicEmail },
|
|
||||||
req.userId,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.register = async (req, res, next) => {
|
exports.register = async (req, res, next) => {
|
||||||
const { name, email, password } = req.body
|
const { name, email, password } = req.body;
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
|
||||||
message: errors.array()[0].msg,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const hashedPassword = await bcrypt.hash(password, 12)
|
const hashedPassword = await bcrypt.hash(password, 12);
|
||||||
const tempToken = uuid.v4()
|
const tempToken = uuid.v4();
|
||||||
await Users.create({ email, name, password: hashedPassword, tempToken })
|
await Users.create({ email, name, password: hashedPassword, tempToken });
|
||||||
await transporter.sendMail({
|
await transporter.sendMail({
|
||||||
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
|
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
|
||||||
to: email,
|
to: email,
|
||||||
subject: "FunctionProject - Confirmer l'inscription",
|
subject: "FunctionProject - Confirmer l'inscription",
|
||||||
html: emailUserTemplate(
|
html: emailUserTemplate("Veuillez confirmer l'inscription", "Oui, je m'inscris.", `${HOST}/users/confirm-email/${tempToken}`, "Si vous avez reçu ce message par erreur, il suffit de le supprimer. Vous ne serez pas inscrit si vous ne cliquez pas sur le lien de confirmation ci-dessus.")
|
||||||
"Veuillez confirmer l'inscription",
|
});
|
||||||
"Oui, je m'inscris.",
|
return res.status(201).json({ result: "Vous y êtes presque, veuillez vérifier vos emails pour confirmer l'inscription." });
|
||||||
`${HOST}/users/confirm-email/${tempToken}`,
|
|
||||||
'Si vous avez reçu ce message par erreur, il suffit de le supprimer. Vous ne serez pas inscrit si vous ne cliquez pas sur le lien de confirmation ci-dessus.'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
.status(201)
|
|
||||||
.json({
|
|
||||||
result:
|
|
||||||
"Vous y êtes presque, veuillez vérifier vos emails pour confirmer l'inscription."
|
|
||||||
})
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.login = async (req, res, next) => {
|
exports.login = async (req, res, next) => {
|
||||||
const { email, password } = req.body
|
const { email, password } = req.body;
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
|
||||||
message: errors.array()[0].msg,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const user = await Users.findOne({ where: { email } })
|
const user = await Users.findOne({ where: { email } });
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Le mot de passe ou l'adresse email n'est pas valide.", statusCode: 400 });
|
||||||
message: "Le mot de passe ou l'adresse email n'est pas valide.",
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const isEqual = await bcrypt.compare(password, user.password)
|
const isEqual = await bcrypt.compare(password, user.password);
|
||||||
if (!isEqual) {
|
if (!isEqual) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Le mot de passe ou l'adresse email n'est pas valide.", statusCode: 400 });
|
||||||
message: "Le mot de passe ou l'adresse email n'est pas valide.",
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (!user.isConfirmed) {
|
if (!user.isConfirmed) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous devez valider votre adresse email pour votre première connexion.", statusCode: 400 });
|
||||||
message:
|
|
||||||
'Vous devez valider votre adresse email pour votre première connexion.',
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const token = jwt.sign(
|
const token = jwt.sign({
|
||||||
{
|
email: user.email, userId: user.id
|
||||||
email: user.email,
|
}, JWT_SECRET, { expiresIn: TOKEN_LIFE });
|
||||||
userId: user.id
|
return res.status(200).json({ token, id: user.id, name: user.name, email: user.email, biography: user.biography, logo: user.logo, isPublicEmail: user.isPublicEmail, isAdmin: user.isAdmin, createdAt: user.createdAt, expiresIn: Math.round(ms(TOKEN_LIFE) / 1000) });
|
||||||
},
|
|
||||||
JWT_SECRET,
|
|
||||||
{ expiresIn: TOKEN_LIFE }
|
|
||||||
)
|
|
||||||
return res
|
|
||||||
.status(200)
|
|
||||||
.json({
|
|
||||||
token,
|
|
||||||
id: user.id,
|
|
||||||
name: user.name,
|
|
||||||
email: user.email,
|
|
||||||
biography: user.biography,
|
|
||||||
logo: user.logo,
|
|
||||||
isPublicEmail: user.isPublicEmail,
|
|
||||||
isAdmin: user.isAdmin,
|
|
||||||
createdAt: user.createdAt,
|
|
||||||
expiresIn: Math.round(ms(TOKEN_LIFE) / 1000)
|
|
||||||
})
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.confirmEmail = async (req, res, next) => {
|
exports.confirmEmail = async (req, res, next) => {
|
||||||
const { tempToken } = req.params
|
const { tempToken } = req.params;
|
||||||
if (!tempToken) {
|
if (!tempToken) {
|
||||||
return errorHandling(next, generalError)
|
return errorHandling(next, generalError);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const user = await Users.findOne({
|
const user = await Users.findOne({ where: { tempToken, isConfirmed: false } });
|
||||||
where: { tempToken, isConfirmed: false }
|
|
||||||
})
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Le token n'est pas valide.", statusCode: 400 });
|
||||||
message: "Le token n'est pas valide.",
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
user.tempToken = null
|
user.tempToken = null;
|
||||||
user.isConfirmed = true
|
user.isConfirmed = true;
|
||||||
await user.save()
|
await user.save();
|
||||||
return res.redirect(`${FRONT_END_HOST}/users/login?isConfirmed=true`)
|
return res.redirect(`${FRONT_END_HOST}/users/login?isConfirmed=true`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.resetPassword = async (req, res, next) => {
|
exports.resetPassword = async (req, res, next) => {
|
||||||
const { email } = req.body
|
const { email } = req.body;
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
|
||||||
message: errors.array()[0].msg,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const user = await Users.findOne({ where: { email, tempToken: null } })
|
const user = await Users.findOne({ where: { email, tempToken: null } });
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "L'adresse email n'existe pas ou une demande est déjà en cours.", statusCode: 400 });
|
||||||
message:
|
|
||||||
"L'adresse email n'existe pas ou une demande est déjà en cours.",
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const tempToken = uuid.v4()
|
const tempToken = uuid.v4();
|
||||||
user.tempExpirationToken = Date.now() + 3600000 // 1 heure
|
user.tempExpirationToken = Date.now() + 3600000; // 1 heure
|
||||||
user.tempToken = tempToken
|
user.tempToken = tempToken;
|
||||||
await user.save()
|
await user.save();
|
||||||
await transporter.sendMail({
|
await transporter.sendMail({
|
||||||
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
|
from: `"FunctionProject" <${EMAIL_INFO.auth.user}>`,
|
||||||
to: email,
|
to: email,
|
||||||
subject: 'FunctionProject - Réinitialisation du mot de passe',
|
subject: "FunctionProject - Réinitialisation du mot de passe",
|
||||||
html: emailUserTemplate(
|
html: emailUserTemplate("Veuillez confirmer la réinitialisation du mot de passe", "Oui, je change mon mot de passe.", `${FRONT_END_HOST}/users/newPassword?token=${tempToken}`, "Si vous avez reçu ce message par erreur, il suffit de le supprimer. Votre mot de passe ne sera pas réinitialiser si vous ne cliquez pas sur le lien ci-dessus. Par ailleurs, pour la sécurité de votre compte, la réinitialisation du mot de passe est disponible pendant un délai de 1 heure, passez ce temps, la réinitialisation ne sera plus valide.")
|
||||||
'Veuillez confirmer la réinitialisation du mot de passe',
|
});
|
||||||
'Oui, je change mon mot de passe.',
|
return res.status(200).json({ result: "Demande de réinitialisation du mot de passe réussi, veuillez vérifier vos emails!" });
|
||||||
`${FRONT_END_HOST}/users/newPassword?token=${tempToken}`,
|
|
||||||
'Si vous avez reçu ce message par erreur, il suffit de le supprimer. Votre mot de passe ne sera pas réinitialiser si vous ne cliquez pas sur le lien ci-dessus. Par ailleurs, pour la sécurité de votre compte, la réinitialisation du mot de passe est disponible pendant un délai de 1 heure, passez ce temps, la réinitialisation ne sera plus valide.'
|
|
||||||
)
|
|
||||||
})
|
|
||||||
return res
|
|
||||||
.status(200)
|
|
||||||
.json({
|
|
||||||
result:
|
|
||||||
'Demande de réinitialisation du mot de passe réussi, veuillez vérifier vos emails!'
|
|
||||||
})
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.newPassword = async (req, res, next) => {
|
exports.newPassword = async (req, res, next) => {
|
||||||
const { tempToken, password } = req.body
|
const { tempToken, password } = req.body;
|
||||||
const errors = validationResult(req)
|
const errors = validationResult(req);
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: errors.array()[0].msg, statusCode: 400 });
|
||||||
message: errors.array()[0].msg,
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const user = await Users.findOne({ where: { tempToken } })
|
const user = await Users.findOne({ where: { tempToken } });
|
||||||
if (!user && parseInt(user.tempExpirationToken) < Date.now()) {
|
if (!user && parseInt(tempExpirationToken) < Date.now()) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Le token n'est pas valide.", statusCode: 400 });
|
||||||
message: "Le token n'est pas valide.",
|
|
||||||
statusCode: 400
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const hashedPassword = await bcrypt.hash(password, 12)
|
const hashedPassword = await bcrypt.hash(password, 12);
|
||||||
user.password = hashedPassword
|
user.password = hashedPassword;
|
||||||
user.tempToken = null
|
user.tempToken = null;
|
||||||
user.tempExpirationToken = null
|
user.tempExpirationToken = null;
|
||||||
await user.save()
|
await user.save();
|
||||||
return res
|
return res.status(200).json({ result: "Le mot de passe a bien été modifié!" });
|
||||||
.status(200)
|
|
||||||
.json({ result: 'Le mot de passe a bien été modifié!' })
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getUserInfo = async (req, res, next) => {
|
exports.getUserInfo = async (req, res, next) => {
|
||||||
const { name } = req.params
|
const { name } = req.params;
|
||||||
try {
|
try {
|
||||||
const user = await Users.findOne({
|
const user = await Users.findOne({
|
||||||
where: { name, isConfirmed: true },
|
where: { name, isConfirmed: true },
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: [
|
exclude: ["updatedAt", "isAdmin", "isConfirmed", "password", "tempToken", "tempExpirationToken"]
|
||||||
'updatedAt',
|
},
|
||||||
'isAdmin',
|
});
|
||||||
'isConfirmed',
|
|
||||||
'password',
|
|
||||||
'tempToken',
|
|
||||||
'tempExpirationToken'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "L'utilisateur n'existe pas.", statusCode: 404 });
|
||||||
message: "L'utilisateur n'existe pas.",
|
|
||||||
statusCode: 404
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const favorites = await Favorites.findAll({
|
const favorites = await Favorites.findAll({
|
||||||
where: { userId: user.id },
|
where: { userId: user.id },
|
||||||
include: [
|
include: [
|
||||||
{
|
{ model: Functions, attributes: { exclude: ["updatedAt", "utilizationForm", "article", "isOnline"] }, include: { model: Categories, attributes: ["name", "color"] } }
|
||||||
model: Functions,
|
|
||||||
attributes: {
|
|
||||||
exclude: ['updatedAt', 'utilizationForm', 'article', 'isOnline']
|
|
||||||
},
|
|
||||||
include: { model: Categories, attributes: ['name', 'color'] }
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
order: [['createdAt', 'DESC']],
|
order: [['createdAt', 'DESC']],
|
||||||
limit: 5
|
limit: 5
|
||||||
})
|
});
|
||||||
const favoritesArray = favorites.map(favorite => favorite.function)
|
const favoritesArray = favorites.map((favorite) => favorite.function);
|
||||||
const comments = await Comments.findAll({
|
const comments = await Comments.findAll({
|
||||||
where: { userId: user.id },
|
where: { userId: user.id },
|
||||||
include: [
|
include: [
|
||||||
{
|
{ model: Functions, attributes: { exclude: ["updatedAt", "utilizationForm", "article", "isOnline"] } }
|
||||||
model: Functions,
|
|
||||||
attributes: {
|
|
||||||
exclude: ['updatedAt', 'utilizationForm', 'article', 'isOnline']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
order: [['createdAt', 'DESC']],
|
order: [['createdAt', 'DESC']],
|
||||||
limit: 5
|
limit: 5
|
||||||
})
|
});
|
||||||
const commentsArray = comments.map(commentObject => {
|
const commentsArray = comments.map((commentObject) => {
|
||||||
return {
|
return {
|
||||||
id: commentObject.id,
|
id: commentObject.id,
|
||||||
message: commentObject.message,
|
message: commentObject.message,
|
||||||
createdAt: commentObject.createdAt,
|
createdAt: commentObject.createdAt,
|
||||||
function: commentObject.function.dataValues
|
function: commentObject.function.dataValues
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
const quotesArray = await Quotes.findAll({
|
const quotesArray = await Quotes.findAll({
|
||||||
where: { userId: user.id, isValidated: 1 },
|
where: { userId: user.id },
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ['updatedAt', 'createdAt', 'isValidated', 'userId', 'id']
|
exclude: ["updatedAt", "createdAt", "isValidated", "userId", "id"]
|
||||||
},
|
},
|
||||||
order: [['createdAt', 'DESC']],
|
order: [['createdAt', 'DESC']],
|
||||||
limit: 5
|
limit: 5,
|
||||||
})
|
});
|
||||||
const userObject = {
|
const userObject = {
|
||||||
// Si Public Email
|
// Si Public Email
|
||||||
...(user.isPublicEmail && { email: user.email }),
|
... (user.isPublicEmail) && { email: user.email },
|
||||||
isPublicEmail: user.isPublicEmail,
|
isPublicEmail: user.isPublicEmail,
|
||||||
name: user.name,
|
name: user.name,
|
||||||
biography: user.biography,
|
biography: user.biography,
|
||||||
@ -445,10 +283,10 @@ exports.getUserInfo = async (req, res, next) => {
|
|||||||
favoritesArray,
|
favoritesArray,
|
||||||
commentsArray,
|
commentsArray,
|
||||||
quotesArray
|
quotesArray
|
||||||
}
|
};
|
||||||
return res.status(200).json(userObject)
|
return res.status(200).json(userObject);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
return errorHandling(next, serverError)
|
return errorHandling(next, serverError);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,32 +1,23 @@
|
|||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const { serverError } = require('../assets/config/errors')
|
const { serverError } = require('../assets/config/errors');
|
||||||
const Users = require('../models/users')
|
const Users = require('../models/users');
|
||||||
|
|
||||||
module.exports = (req, _res, next) => {
|
module.exports = (req, _res, next) => {
|
||||||
if (!req.userId) {
|
if (!req.userId) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous n'êtes pas connecté.", statusCode: 403 });
|
||||||
message: "Vous n'êtes pas connecté.",
|
|
||||||
statusCode: 403
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
Users.findOne({ where: { id: req.userId } })
|
Users.findOne({ where: { id: req.userId } })
|
||||||
.then(user => {
|
.then((user) => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Le mot de passe ou l'adresse email n'est pas valide.", statusCode: 403 });
|
||||||
message: "Le mot de passe ou l'adresse email n'est pas valide.",
|
|
||||||
statusCode: 403
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (!user.isAdmin) {
|
if (!user.isAdmin) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous n'êtes pas administrateur.", statusCode: 403 });
|
||||||
message: "Vous n'êtes pas administrateur.",
|
|
||||||
statusCode: 403
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
next()
|
next();
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error)
|
|
||||||
return errorHandling(next, serverError)
|
|
||||||
})
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
return errorHandling(next, serverError);
|
||||||
|
});
|
||||||
}
|
}
|
@ -1,33 +1,24 @@
|
|||||||
const jwt = require('jsonwebtoken')
|
const jwt = require('jsonwebtoken');
|
||||||
const errorHandling = require('../assets/utils/errorHandling')
|
const errorHandling = require('../assets/utils/errorHandling');
|
||||||
const { JWT_SECRET } = require('../assets/config/config')
|
const { JWT_SECRET } = require('../assets/config/config');
|
||||||
|
|
||||||
module.exports = (req, _res, next) => {
|
module.exports = (req, _res, next) => {
|
||||||
const token = req.get('Authorization')
|
const token = req.get('Authorization');
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous devez être connecter pour effectuer cette opération.", statusCode: 403 });
|
||||||
message: 'Vous devez être connecter pour effectuer cette opération.',
|
|
||||||
statusCode: 403
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let decodedToken
|
let decodedToken;
|
||||||
try {
|
try {
|
||||||
decodedToken = jwt.verify(token, JWT_SECRET)
|
decodedToken = jwt.verify(token, JWT_SECRET);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous devez être connecter pour effectuer cette opération.", statusCode: 403 });
|
||||||
message: 'Vous devez être connecter pour effectuer cette opération.',
|
|
||||||
statusCode: 403
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!decodedToken) {
|
if (!decodedToken) {
|
||||||
return errorHandling(next, {
|
return errorHandling(next, { message: "Vous devez être connecter pour effectuer cette opération.", statusCode: 403 });
|
||||||
message: 'Vous devez être connecter pour effectuer cette opération.',
|
|
||||||
statusCode: 403
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
req.userId = decodedToken.userId
|
req.userId = decodedToken.userId;
|
||||||
next()
|
next();
|
||||||
}
|
}
|
@ -1,13 +1,13 @@
|
|||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const sequelize = require('../assets/utils/database')
|
const sequelize = require('../assets/utils/database');
|
||||||
|
|
||||||
module.exports = sequelize.define('categorie', {
|
module.exports = sequelize.define('categorie', {
|
||||||
name: {
|
name: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
color: {
|
color: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
}
|
}
|
||||||
})
|
});
|
@ -1,9 +1,9 @@
|
|||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const sequelize = require('../assets/utils/database')
|
const sequelize = require('../assets/utils/database');
|
||||||
|
|
||||||
module.exports = sequelize.define('comment', {
|
module.exports = sequelize.define('comment', {
|
||||||
message: {
|
message: {
|
||||||
type: Sequelize.TEXT,
|
type: Sequelize.TEXT,
|
||||||
allowNull: false
|
allowNull: false
|
||||||
}
|
}
|
||||||
})
|
});
|
@ -1,3 +1,4 @@
|
|||||||
const sequelize = require('../assets/utils/database')
|
const Sequelize = require('sequelize');
|
||||||
|
const sequelize = require('../assets/utils/database');
|
||||||
|
|
||||||
module.exports = sequelize.define('favorite', {})
|
module.exports = sequelize.define('favorite', {});
|
@ -1,14 +1,14 @@
|
|||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const sequelize = require('../assets/utils/database')
|
const sequelize = require('../assets/utils/database');
|
||||||
|
|
||||||
module.exports = sequelize.define('function', {
|
module.exports = sequelize.define('function', {
|
||||||
title: {
|
title: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
slug: {
|
slug: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
@ -17,7 +17,7 @@ module.exports = sequelize.define('function', {
|
|||||||
image: {
|
image: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue: '/images/functions/default.png'
|
defaultValue: "/images/functions/default.png"
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
@ -36,4 +36,4 @@ module.exports = sequelize.define('function', {
|
|||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue: 0
|
defaultValue: 0
|
||||||
}
|
}
|
||||||
})
|
});
|
@ -1,18 +1,18 @@
|
|||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const sequelize = require('../assets/utils/database')
|
const sequelize = require('../assets/utils/database');
|
||||||
|
|
||||||
module.exports = sequelize.define('quote', {
|
module.exports = sequelize.define('quote', {
|
||||||
quote: {
|
quote: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
author: {
|
author: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
isValidated: {
|
isValidated: {
|
||||||
type: Sequelize.BOOLEAN,
|
type: Sequelize.BOOLEAN,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue: 0
|
defaultValue: 0
|
||||||
}
|
}
|
||||||
})
|
});
|
@ -1,18 +1,13 @@
|
|||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const sequelize = require('../assets/utils/database')
|
const sequelize = require('../assets/utils/database');
|
||||||
|
|
||||||
module.exports = sequelize.define('short_link', {
|
module.exports = sequelize.define('short_link', {
|
||||||
url: {
|
url: {
|
||||||
type: Sequelize.TEXT,
|
type: Sequelize.TEXT,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
shortcut: {
|
shortcut: {
|
||||||
type: Sequelize.TEXT,
|
type: Sequelize.TEXT,
|
||||||
allowNull: false
|
|
||||||
},
|
|
||||||
count: {
|
|
||||||
type: Sequelize.INTEGER,
|
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue: 0
|
|
||||||
}
|
}
|
||||||
})
|
});
|
@ -1,14 +1,14 @@
|
|||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const sequelize = require('../assets/utils/database')
|
const sequelize = require('../assets/utils/database');
|
||||||
|
|
||||||
module.exports = sequelize.define('task', {
|
module.exports = sequelize.define('task', {
|
||||||
task: {
|
task: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
isCompleted: {
|
isCompleted: {
|
||||||
type: Sequelize.BOOLEAN,
|
type: Sequelize.BOOLEAN,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue: 0
|
defaultValue: 0
|
||||||
}
|
}
|
||||||
})
|
});
|
@ -1,26 +1,26 @@
|
|||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize');
|
||||||
const sequelize = require('../assets/utils/database')
|
const sequelize = require('../assets/utils/database');
|
||||||
|
|
||||||
module.exports = sequelize.define('user', {
|
module.exports = sequelize.define('user', {
|
||||||
name: {
|
name: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
password: {
|
password: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
allowNull: false
|
allowNull: false,
|
||||||
},
|
},
|
||||||
biography: {
|
biography: {
|
||||||
type: Sequelize.TEXT,
|
type: Sequelize.TEXT,
|
||||||
defaultValue: ''
|
defaultValue: ""
|
||||||
},
|
},
|
||||||
logo: {
|
logo: {
|
||||||
type: Sequelize.STRING,
|
type: Sequelize.STRING,
|
||||||
defaultValue: '/images/users/default.png'
|
defaultValue: "/images/users/default.png"
|
||||||
},
|
},
|
||||||
isConfirmed: {
|
isConfirmed: {
|
||||||
type: Sequelize.BOOLEAN,
|
type: Sequelize.BOOLEAN,
|
||||||
@ -42,4 +42,4 @@ module.exports = sequelize.define('user', {
|
|||||||
type: Sequelize.DATE,
|
type: Sequelize.DATE,
|
||||||
allowNull: true
|
allowNull: true
|
||||||
}
|
}
|
||||||
})
|
});
|
9334
api/package-lock.json
generated
@ -1,46 +1,38 @@
|
|||||||
{
|
{
|
||||||
"name": "api",
|
"name": "api",
|
||||||
"version": "2.3.0",
|
"version": "2.0.0",
|
||||||
"description": "Backend REST API for FunctionProject",
|
"description": "Backend REST API for FunctionProject",
|
||||||
"standard": {
|
"main": "app.js",
|
||||||
"files": [
|
|
||||||
"./**/*.js"
|
|
||||||
],
|
|
||||||
"envs": [
|
|
||||||
"node"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node app.js",
|
"start": "node app.js",
|
||||||
"dev": "nodemon app.js",
|
"dev": "nodemon app.js"
|
||||||
"lint": "standard | snazzy"
|
|
||||||
},
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Divlo",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.19.2",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^8.2.0",
|
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-fileupload": "^1.2.1",
|
"express-fileupload": "^1.1.6",
|
||||||
"express-http-to-https": "^1.1.4",
|
"express-http-to-https": "^1.1.4",
|
||||||
"express-rate-limit": "^5.2.6",
|
"express-validator": "^6.4.0",
|
||||||
"express-validator": "^6.10.0",
|
"helmet": "^3.21.3",
|
||||||
"helmet": "^4.4.1",
|
|
||||||
"jsdom": "^16.5.3",
|
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.24.0",
|
||||||
"morgan": "^1.10.0",
|
"ms": "^2.1.2",
|
||||||
"ms": "^2.1.3",
|
"mysql2": "^2.1.0",
|
||||||
"mysql2": "^2.2.5",
|
"nodemailer": "^6.4.6",
|
||||||
"nodemailer": "^6.5.0",
|
"sequelize": "^5.21.5",
|
||||||
"sequelize": "^6.6.2",
|
|
||||||
"smart-request-balancer": "^2.1.1",
|
"smart-request-balancer": "^2.1.1",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^7.0.2",
|
||||||
"validator": "^13.5.2"
|
"validator": "^13.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"nodemon": "^2.0.7",
|
"dotenv": "^8.2.0",
|
||||||
"snazzy": "^9.0.0",
|
"morgan": "^1.9.1",
|
||||||
"standard": "^16.0.3"
|
"nightmare": "^3.0.2",
|
||||||
|
"nodemon": "^2.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
const { Router } = require('express')
|
const { Router } = require('express');
|
||||||
const fileUpload = require('express-fileupload')
|
const fileUpload = require('express-fileupload');
|
||||||
const { body } = require('express-validator')
|
const { body } = require('express-validator');
|
||||||
const adminController = require('../controllers/admin')
|
const adminController = require('../controllers/admin');
|
||||||
const Functions = require('../models/functions')
|
const Functions = require('../models/functions');
|
||||||
const Categories = require('../models/categories')
|
const Categories = require('../models/categories');
|
||||||
|
|
||||||
const AdminRouter = Router()
|
const AdminRouter = Router();
|
||||||
|
|
||||||
AdminRouter.route('/functions')
|
AdminRouter.route('/functions')
|
||||||
|
|
||||||
@ -13,8 +13,7 @@ AdminRouter.route('/functions')
|
|||||||
.get(adminController.getFunctions)
|
.get(adminController.getFunctions)
|
||||||
|
|
||||||
// Permet de créé une fonction
|
// Permet de créé une fonction
|
||||||
.post(
|
.post(fileUpload({
|
||||||
fileUpload({
|
|
||||||
useTempFiles: true,
|
useTempFiles: true,
|
||||||
safeFileNames: true,
|
safeFileNames: true,
|
||||||
preserveExtension: Number,
|
preserveExtension: Number,
|
||||||
@ -25,93 +24,83 @@ AdminRouter.route('/functions')
|
|||||||
body('title')
|
body('title')
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('La fonction doit avoir un titre.')
|
.withMessage("La fonction doit avoir un titre.")
|
||||||
.isLength({ max: 100 })
|
.isLength({ max: 100 })
|
||||||
.withMessage('Le titre est trop long.')
|
.withMessage("Le titre est trop long.")
|
||||||
.custom(title => {
|
.custom(((title) => {
|
||||||
if (title === 'undefined') {
|
if (title === 'undefined') {
|
||||||
return Promise.reject(new Error('La fonction doit avoir un titre.'))
|
return Promise.reject("La fonction doit avoir un titre.");
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
})),
|
||||||
body('slug')
|
body('slug')
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('La fonction doit avoir un slug.')
|
.withMessage("La fonction doit avoir un slug.")
|
||||||
.isLength({ max: 100 })
|
.isLength({ max: 100 })
|
||||||
.withMessage('Le slug est trop long.')
|
.withMessage("Le slug est trop long.")
|
||||||
.custom(slug => {
|
.custom(((slug) => {
|
||||||
if (slug === 'undefined') {
|
if (slug === 'undefined') {
|
||||||
return Promise.reject(new Error('La fonction doit avoir un slug.'))
|
return Promise.reject("La fonction doit avoir un slug.");
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
})
|
}))
|
||||||
.custom(async slug => {
|
.custom((async (slug) => {
|
||||||
try {
|
try {
|
||||||
const FunctionSlug = await Functions.findOne({ where: { slug } })
|
const FunctionSlug = await Functions.findOne({ where: { slug } });
|
||||||
if (FunctionSlug) {
|
if (FunctionSlug) {
|
||||||
return Promise.reject(new Error('Le slug existe déjà...'))
|
return Promise.reject("Le slug existe déjà...");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
})),
|
||||||
body('description')
|
body('description')
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('La fonction doit avoir une description.')
|
.withMessage("La fonction doit avoir une description.")
|
||||||
.isLength({ max: 255, min: 1 })
|
.isLength({ max: 255, min: 1 })
|
||||||
.withMessage('La description est trop longue.')
|
.withMessage("La description est trop longue.")
|
||||||
.custom(description => {
|
.custom(((description) => {
|
||||||
if (description === 'undefined') {
|
if (description === 'undefined') {
|
||||||
return Promise.reject(
|
return Promise.reject("La fonction doit avoir une description.");
|
||||||
new Error('La fonction doit avoir une description.')
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
})),
|
||||||
body('categorieId')
|
body('categorieId')
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('La fonction doit avoir une catégorie.')
|
.withMessage("La fonction doit avoir une catégorie.")
|
||||||
.custom(async categorieId => {
|
.custom(async (categorieId) => {
|
||||||
try {
|
try {
|
||||||
const categorieFound = await Categories.findOne({
|
const categorieFound = await Categories.findOne({ where: { id: parseInt(categorieId) } });
|
||||||
where: { id: parseInt(categorieId) }
|
|
||||||
})
|
|
||||||
if (!categorieFound) {
|
if (!categorieFound) {
|
||||||
return Promise.reject(new Error("La catégorie n'existe pas!"))
|
return Promise.reject("La catégorie n'existe pas!");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
}),
|
||||||
body('type').custom(type => {
|
body('type')
|
||||||
|
.custom((type) => {
|
||||||
if (!(type === 'article' || type === 'form' || type === 'page')) {
|
if (!(type === 'article' || type === 'form' || type === 'page')) {
|
||||||
return Promise.reject(
|
return Promise.reject('Le type de la fonction peut être : article, form ou page.');
|
||||||
new Error(
|
|
||||||
'Le type de la fonction peut être : article, form ou page.'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
})
|
})
|
||||||
],
|
], adminController.postFunction);
|
||||||
adminController.postFunction
|
|
||||||
)
|
|
||||||
|
|
||||||
AdminRouter.route('/functions/:slug')
|
AdminRouter.route('/functions/:slug')
|
||||||
|
|
||||||
// Récupère les informations d'une fonction
|
// Récupère les informations d'une fonction
|
||||||
.get(adminController.getFunctionBySlug)
|
.get(adminController.getFunctionBySlug);
|
||||||
|
|
||||||
AdminRouter.route('/functions/:id')
|
AdminRouter.route('/functions/:id')
|
||||||
|
|
||||||
// Modifie information basique d'une fonction
|
// Modifie information basique d'une fonction
|
||||||
.put(
|
.put(fileUpload({
|
||||||
fileUpload({
|
|
||||||
useTempFiles: true,
|
useTempFiles: true,
|
||||||
safeFileNames: true,
|
safeFileNames: true,
|
||||||
preserveExtension: Number,
|
preserveExtension: Number,
|
||||||
@ -122,85 +111,78 @@ AdminRouter.route('/functions/:id')
|
|||||||
body('title')
|
body('title')
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('La fonction doit avoir un titre.')
|
.withMessage("La fonction doit avoir un titre.")
|
||||||
.isLength({ max: 100 })
|
.isLength({ max: 100 })
|
||||||
.withMessage('Le titre est trop long.')
|
.withMessage("Le titre est trop long.")
|
||||||
.custom(title => {
|
.custom(((title) => {
|
||||||
if (title === 'undefined') {
|
if (title === 'undefined') {
|
||||||
return Promise.reject(new Error('La fonction doit avoir un titre.'))
|
return Promise.reject("La fonction doit avoir un titre.");
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
})),
|
||||||
body('slug')
|
body('slug')
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('La fonction doit avoir un slug.')
|
.withMessage("La fonction doit avoir un slug.")
|
||||||
.isLength({ max: 100 })
|
.isLength({ max: 100 })
|
||||||
.withMessage('Le slug est trop long.')
|
.withMessage("Le slug est trop long.")
|
||||||
.custom(slug => {
|
.custom(((slug) => {
|
||||||
if (slug === 'undefined') {
|
if (slug === 'undefined') {
|
||||||
return Promise.reject(new Error('La fonction doit avoir un slug.'))
|
return Promise.reject("La fonction doit avoir un slug.");
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
})),
|
||||||
body('description')
|
body('description')
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('La fonction doit avoir une description.')
|
.withMessage("La fonction doit avoir une description.")
|
||||||
.isLength({ max: 255, min: 1 })
|
.isLength({ max: 255, min: 1 })
|
||||||
.withMessage('La description est trop longue.')
|
.withMessage("La description est trop longue.")
|
||||||
.custom(description => {
|
.custom(((description) => {
|
||||||
if (description === 'undefined') {
|
if (description === 'undefined') {
|
||||||
return Promise.reject(
|
return Promise.reject("La fonction doit avoir une description.");
|
||||||
new Error('La fonction doit avoir une description.')
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
})),
|
||||||
body('categorieId')
|
body('categorieId')
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('La fonction doit avoir une catégorie.')
|
.withMessage("La fonction doit avoir une catégorie.")
|
||||||
.custom(async categorieId => {
|
.custom(async (categorieId) => {
|
||||||
try {
|
try {
|
||||||
const categorieFound = await Categories.findOne({
|
const categorieFound = await Categories.findOne({ where: { id: parseInt(categorieId) } });
|
||||||
where: { id: parseInt(categorieId) }
|
|
||||||
})
|
|
||||||
if (!categorieFound) {
|
if (!categorieFound) {
|
||||||
return Promise.reject(new Error("La catégorie n'existe pas!"))
|
return Promise.reject("La catégorie n'existe pas!");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
}),
|
||||||
body('type').custom(type => {
|
body('type')
|
||||||
|
.custom((type) => {
|
||||||
if (!(type === 'article' || type === 'form' || type === 'page')) {
|
if (!(type === 'article' || type === 'form' || type === 'page')) {
|
||||||
return Promise.reject(
|
return Promise.reject('Le type de la fonction peut être : article, form ou page.');
|
||||||
new Error(
|
|
||||||
'Le type de la fonction peut être : article, form ou page.'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
})
|
})
|
||||||
],
|
], adminController.putFunction)
|
||||||
adminController.putFunction
|
|
||||||
)
|
|
||||||
|
|
||||||
// Supprime une fonction avec son id
|
// Supprime une fonction avec son id
|
||||||
.delete(adminController.deleteFunction)
|
.delete(adminController.deleteFunction);
|
||||||
|
|
||||||
AdminRouter.route('/functions/article/:id')
|
AdminRouter.route('/functions/article/:id')
|
||||||
.put(adminController.putFunctionArticle)
|
|
||||||
|
.put(adminController.putFunctionArticle);
|
||||||
|
|
||||||
AdminRouter.route('/functions/form/:id')
|
AdminRouter.route('/functions/form/:id')
|
||||||
.put(adminController.putFunctionForm)
|
|
||||||
|
.put(adminController.putFunctionForm);
|
||||||
|
|
||||||
AdminRouter.route('/categories')
|
AdminRouter.route('/categories')
|
||||||
|
|
||||||
// Crée une catégorie
|
// Crée une catégorie
|
||||||
.post(adminController.postCategory)
|
.post(adminController.postCategory);
|
||||||
|
|
||||||
AdminRouter.route('/categories/:id')
|
AdminRouter.route('/categories/:id')
|
||||||
|
|
||||||
@ -208,16 +190,16 @@ AdminRouter.route('/categories/:id')
|
|||||||
.put(adminController.putCategory)
|
.put(adminController.putCategory)
|
||||||
|
|
||||||
// Supprime une catégorie avec son id
|
// Supprime une catégorie avec son id
|
||||||
.delete(adminController.deleteCategory)
|
.delete(adminController.deleteCategory);
|
||||||
|
|
||||||
AdminRouter.route('/quotes')
|
AdminRouter.route('/quotes')
|
||||||
|
|
||||||
// Récupère les citations pas encore validées
|
// Récupère les citations pas encore validées
|
||||||
.get(adminController.getQuotes)
|
.get(adminController.getQuotes);
|
||||||
|
|
||||||
AdminRouter.route('/quotes/:id')
|
AdminRouter.route('/quotes/:id')
|
||||||
|
|
||||||
// Valide ou supprime une citation
|
// Valide ou supprime une citation
|
||||||
.put(adminController.putQuote)
|
.put(adminController.putQuote);
|
||||||
|
|
||||||
module.exports = AdminRouter
|
module.exports = AdminRouter;
|
@ -1,11 +1,11 @@
|
|||||||
const { Router } = require('express')
|
const { Router } = require('express');
|
||||||
const categoriesController = require('../controllers/categories')
|
const categoriesController = require('../controllers/categories');
|
||||||
|
|
||||||
const CategoriesRouter = Router()
|
const CategoriesRouter = Router();
|
||||||
|
|
||||||
CategoriesRouter.route('/')
|
CategoriesRouter.route('/')
|
||||||
|
|
||||||
// Récupère les catégories
|
// Récupère les catégories
|
||||||
.get(categoriesController.getCategories)
|
.get(categoriesController.getCategories);
|
||||||
|
|
||||||
module.exports = CategoriesRouter
|
module.exports = CategoriesRouter;
|
@ -1,8 +1,8 @@
|
|||||||
const { Router } = require('express')
|
const { Router } = require('express');
|
||||||
const commentsController = require('../controllers/comments')
|
const commentsController = require('../controllers/comments');
|
||||||
const isAuth = require('../middlewares/isAuth')
|
const isAuth = require('../middlewares/isAuth');
|
||||||
|
|
||||||
const CommentsRouter = Router()
|
const CommentsRouter = Router();
|
||||||
|
|
||||||
CommentsRouter.route('/:commentId')
|
CommentsRouter.route('/:commentId')
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ CommentsRouter.route('/:commentId')
|
|||||||
.put(isAuth, commentsController.putCommentsById)
|
.put(isAuth, commentsController.putCommentsById)
|
||||||
|
|
||||||
// Supprime un commentaire
|
// Supprime un commentaire
|
||||||
.delete(isAuth, commentsController.deleteCommentById)
|
.delete(isAuth, commentsController.deleteCommentById);
|
||||||
|
|
||||||
CommentsRouter.route('/:functionId')
|
CommentsRouter.route('/:functionId')
|
||||||
|
|
||||||
@ -18,6 +18,6 @@ CommentsRouter.route('/:functionId')
|
|||||||
.get(commentsController.getCommentsByFunctionId)
|
.get(commentsController.getCommentsByFunctionId)
|
||||||
|
|
||||||
// Permet à un utilisateur de poster un commentaire sur une fonction
|
// Permet à un utilisateur de poster un commentaire sur une fonction
|
||||||
.post(isAuth, commentsController.postCommentsByFunctionId)
|
.post(isAuth, commentsController.postCommentsByFunctionId);
|
||||||
|
|
||||||
module.exports = CommentsRouter
|
module.exports = CommentsRouter;
|
@ -1,8 +1,8 @@
|
|||||||
const { Router } = require('express')
|
const { Router } = require('express');
|
||||||
const favoritesController = require('../controllers/favorites')
|
const favoritesController = require('../controllers/favorites');
|
||||||
const isAuth = require('../middlewares/isAuth')
|
const isAuth = require('../middlewares/isAuth');
|
||||||
|
|
||||||
const FavoritesRouter = Router()
|
const FavoritesRouter = Router();
|
||||||
|
|
||||||
FavoritesRouter.route('/:functionId')
|
FavoritesRouter.route('/:functionId')
|
||||||
|
|
||||||
@ -13,6 +13,6 @@ FavoritesRouter.route('/:functionId')
|
|||||||
.post(isAuth, favoritesController.postFavoriteByFunctionId)
|
.post(isAuth, favoritesController.postFavoriteByFunctionId)
|
||||||
|
|
||||||
// Supprime une fonction des favoris d'un utilisateur
|
// Supprime une fonction des favoris d'un utilisateur
|
||||||
.delete(isAuth, favoritesController.deleteFavoriteByFunctionId)
|
.delete(isAuth, favoritesController.deleteFavoriteByFunctionId);
|
||||||
|
|
||||||
module.exports = FavoritesRouter
|
module.exports = FavoritesRouter;
|
@ -1,12 +1,12 @@
|
|||||||
const { Router } = require('express')
|
const { Router } = require('express');
|
||||||
const functionsController = require('../controllers/functions')
|
const functionsController = require('../controllers/functions');
|
||||||
|
|
||||||
const FunctionsRouter = Router()
|
const FunctionsRouter = Router();
|
||||||
|
|
||||||
FunctionsRouter.route('/')
|
FunctionsRouter.route('/')
|
||||||
|
|
||||||
// Récupère les fonctions
|
// Récupère les fonctions
|
||||||
.get(functionsController.getFunctions)
|
.get(functionsController.getFunctions);
|
||||||
|
|
||||||
FunctionsRouter.route('/:slug')
|
FunctionsRouter.route('/:slug')
|
||||||
|
|
||||||
@ -14,6 +14,6 @@ FunctionsRouter.route('/:slug')
|
|||||||
.get(functionsController.getFunctionBySlug)
|
.get(functionsController.getFunctionBySlug)
|
||||||
|
|
||||||
// Exécute la fonction demandée en paramètre
|
// Exécute la fonction demandée en paramètre
|
||||||
.post(functionsController.executeFunctionBySlug)
|
.post(functionsController.executeFunctionBySlug);
|
||||||
|
|
||||||
module.exports = FunctionsRouter
|
module.exports = FunctionsRouter;
|
@ -1,23 +0,0 @@
|
|||||||
const { Router } = require('express')
|
|
||||||
const linksShortenerController = require('../controllers/links_shortener')
|
|
||||||
const isAuth = require('../middlewares/isAuth')
|
|
||||||
|
|
||||||
const LinksShortenerRouter = Router()
|
|
||||||
|
|
||||||
LinksShortenerRouter.route('/')
|
|
||||||
|
|
||||||
// Récupère les liens d'un utilisateur
|
|
||||||
.get(isAuth, linksShortenerController.getLinks)
|
|
||||||
|
|
||||||
// Ajouter un lien à raccourcir d'un utilisateur
|
|
||||||
.post(isAuth, linksShortenerController.postLink)
|
|
||||||
|
|
||||||
LinksShortenerRouter.route('/:id')
|
|
||||||
|
|
||||||
// Permet de modifier le lien raccourci d'un utilisateur
|
|
||||||
.put(isAuth, linksShortenerController.putLink)
|
|
||||||
|
|
||||||
// Supprimer un lien d'un utilisateur
|
|
||||||
.delete(isAuth, linksShortenerController.deleteLink)
|
|
||||||
|
|
||||||
module.exports = LinksShortenerRouter
|
|
@ -1,8 +1,8 @@
|
|||||||
const { Router } = require('express')
|
const { Router } = require('express');
|
||||||
const quotesController = require('../controllers/quotes')
|
const quotesController = require('../controllers/quotes');
|
||||||
const isAuth = require('../middlewares/isAuth')
|
const isAuth = require('../middlewares/isAuth');
|
||||||
|
|
||||||
const QuotesRouter = Router()
|
const QuotesRouter = Router();
|
||||||
|
|
||||||
QuotesRouter.route('/')
|
QuotesRouter.route('/')
|
||||||
|
|
||||||
@ -10,6 +10,6 @@ QuotesRouter.route('/')
|
|||||||
.get(quotesController.getQuotes)
|
.get(quotesController.getQuotes)
|
||||||
|
|
||||||
// Proposer une citation
|
// Proposer une citation
|
||||||
.post(isAuth, quotesController.postQuote)
|
.post(isAuth, quotesController.postQuote);
|
||||||
|
|
||||||
module.exports = QuotesRouter
|
module.exports = QuotesRouter;
|
@ -1,8 +1,8 @@
|
|||||||
const { Router } = require('express')
|
const { Router } = require('express');
|
||||||
const tasksController = require('../controllers/tasks')
|
const tasksController = require('../controllers/tasks');
|
||||||
const isAuth = require('../middlewares/isAuth')
|
const isAuth = require('../middlewares/isAuth');
|
||||||
|
|
||||||
const TasksRouter = Router()
|
const TasksRouter = Router();
|
||||||
|
|
||||||
TasksRouter.route('/')
|
TasksRouter.route('/')
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ TasksRouter.route('/')
|
|||||||
.get(isAuth, tasksController.getTasks)
|
.get(isAuth, tasksController.getTasks)
|
||||||
|
|
||||||
// Poster une nouvelle tâche à faire
|
// Poster une nouvelle tâche à faire
|
||||||
.post(isAuth, tasksController.postTask)
|
.post(isAuth, tasksController.postTask);
|
||||||
|
|
||||||
TasksRouter.route('/:id')
|
TasksRouter.route('/:id')
|
||||||
|
|
||||||
@ -18,6 +18,6 @@ TasksRouter.route('/:id')
|
|||||||
.put(isAuth, tasksController.putTask)
|
.put(isAuth, tasksController.putTask)
|
||||||
|
|
||||||
// Supprimer une tâche à faire
|
// Supprimer une tâche à faire
|
||||||
.delete(isAuth, tasksController.deleteTask)
|
.delete(isAuth, tasksController.deleteTask);
|
||||||
|
|
||||||
module.exports = TasksRouter
|
module.exports = TasksRouter;
|
@ -1,12 +1,12 @@
|
|||||||
const { Router } = require('express')
|
const { Router } = require('express');
|
||||||
const { body } = require('express-validator')
|
const { body } = require('express-validator');
|
||||||
const fileUpload = require('express-fileupload')
|
const fileUpload = require('express-fileupload');
|
||||||
const usersController = require('../controllers/users')
|
const usersController = require('../controllers/users');
|
||||||
const { requiredFields } = require('../assets/config/errors')
|
const { requiredFields } = require('../assets/config/errors');
|
||||||
const Users = require('../models/users')
|
const Users = require('../models/users');
|
||||||
const isAuth = require('../middlewares/isAuth')
|
const isAuth = require('../middlewares/isAuth');
|
||||||
|
|
||||||
const UsersRouter = Router()
|
const UsersRouter = Router();
|
||||||
|
|
||||||
UsersRouter.route('/')
|
UsersRouter.route('/')
|
||||||
|
|
||||||
@ -14,8 +14,7 @@ UsersRouter.route('/')
|
|||||||
.get(usersController.getUsers)
|
.get(usersController.getUsers)
|
||||||
|
|
||||||
// Permet de modifier son profil
|
// Permet de modifier son profil
|
||||||
.put(
|
.put(isAuth,
|
||||||
isAuth,
|
|
||||||
fileUpload({
|
fileUpload({
|
||||||
useTempFiles: true,
|
useTempFiles: true,
|
||||||
safeFileNames: true,
|
safeFileNames: true,
|
||||||
@ -26,57 +25,49 @@ UsersRouter.route('/')
|
|||||||
[
|
[
|
||||||
body('email')
|
body('email')
|
||||||
.isEmail()
|
.isEmail()
|
||||||
.withMessage('Veuillez rentré une adresse mail valide.')
|
.withMessage("Veuillez rentré une adresse mail valide.")
|
||||||
.custom(async email => {
|
.custom((async (email) => {
|
||||||
try {
|
try {
|
||||||
const user = await Users.findOne({ where: { email } })
|
const user = await Users.findOne({ where: { email } });
|
||||||
if (user && user.email !== email) {
|
if (user && user.email !== email) {
|
||||||
return Promise.reject(new Error("L'adresse email existe déjà..."))
|
return Promise.reject("L'adresse email existe déjà...");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return console.log(error)
|
return console.log(error);
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
})
|
}))
|
||||||
.normalizeEmail(),
|
.normalizeEmail(),
|
||||||
body('name')
|
body('name')
|
||||||
.trim()
|
.trim()
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('Vous devez avoir un nom (ou pseudo).')
|
.withMessage("Vous devez avoir un nom (ou pseudo).")
|
||||||
.isAlphanumeric()
|
.isAlphanumeric()
|
||||||
.withMessage(
|
.withMessage("Votre nom ne peut contenir que des lettres ou/et des nombres.")
|
||||||
'Votre nom ne peut contenir que des lettres ou/et des nombres.'
|
|
||||||
)
|
|
||||||
.isLength({ max: 30 })
|
.isLength({ max: 30 })
|
||||||
.withMessage('Votre nom est trop long')
|
.withMessage("Votre nom est trop long")
|
||||||
.custom(async name => {
|
.custom(async (name) => {
|
||||||
try {
|
try {
|
||||||
const user = await Users.findOne({ where: { name } })
|
const user = await Users.findOne({ where: { name } });
|
||||||
if (user && user.name !== name) {
|
if (user && user.name !== name) {
|
||||||
return Promise.reject(new Error('Le nom existe déjà...'))
|
return Promise.reject("Le nom existe déjà...");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
}),
|
||||||
body('isPublicEmail')
|
body('isPublicEmail')
|
||||||
.isBoolean()
|
.isBoolean()
|
||||||
.withMessage(
|
.withMessage("L'adresse email peut être public ou privé, rien d'autre."),
|
||||||
"L'adresse email peut être public ou privé, rien d'autre."
|
|
||||||
),
|
|
||||||
body('biography')
|
body('biography')
|
||||||
.trim()
|
.trim()
|
||||||
.escape()
|
.escape()
|
||||||
],
|
], usersController.putUser);
|
||||||
usersController.putUser
|
|
||||||
)
|
|
||||||
|
|
||||||
// Permet de se connecter
|
// Permet de se connecter
|
||||||
UsersRouter.post(
|
UsersRouter.post('/login', [
|
||||||
'/login',
|
|
||||||
[
|
|
||||||
body('email')
|
body('email')
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
@ -85,83 +76,70 @@ UsersRouter.post(
|
|||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage(requiredFields.message)
|
.withMessage(requiredFields.message)
|
||||||
],
|
], usersController.login);
|
||||||
usersController.login
|
|
||||||
)
|
|
||||||
|
|
||||||
// Récupère les informations public d'un profil
|
// Récupère les informations public d'un profil
|
||||||
UsersRouter.get('/:name', usersController.getUserInfo)
|
UsersRouter.get('/:name', usersController.getUserInfo);
|
||||||
|
|
||||||
// Permet de s'inscrire
|
// Permet de s'inscrire
|
||||||
UsersRouter.post(
|
UsersRouter.post('/register', [
|
||||||
'/register',
|
|
||||||
[
|
|
||||||
body('email')
|
body('email')
|
||||||
.isEmail()
|
.isEmail()
|
||||||
.withMessage('Veuillez rentré une adresse mail valide.')
|
.withMessage("Veuillez rentré une adresse mail valide.")
|
||||||
.custom(async email => {
|
.custom((async (email) => {
|
||||||
try {
|
try {
|
||||||
const user = await Users.findOne({ where: { email } })
|
const user = await Users.findOne({ where: { email } });
|
||||||
if (user) {
|
if (user) {
|
||||||
return Promise.reject(new Error("L'adresse email existe déjà..."))
|
return Promise.reject("L'adresse email existe déjà...");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return console.log(error)
|
return console.log(error);
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
}),
|
}))
|
||||||
|
.normalizeEmail(),
|
||||||
body('password')
|
body('password')
|
||||||
.isLength({ min: 4 })
|
.isLength({ min: 4 })
|
||||||
.withMessage('Votre mot de passe est trop court!'),
|
.withMessage("Votre mot de passe est trop court!"),
|
||||||
body('name')
|
body('name')
|
||||||
.trim()
|
.trim()
|
||||||
.not()
|
.not()
|
||||||
.isEmpty()
|
.isEmpty()
|
||||||
.withMessage('Vous devez avoir un nom (ou pseudo).')
|
.withMessage("Vous devez avoir un nom (ou pseudo).")
|
||||||
.isAlphanumeric()
|
.isAlphanumeric()
|
||||||
.withMessage(
|
.withMessage("Votre nom ne peut contenir que des lettres ou/et des nombres.")
|
||||||
'Votre nom ne peut contenir que des lettres ou/et des nombres.'
|
|
||||||
)
|
|
||||||
.isLength({ max: 30 })
|
.isLength({ max: 30 })
|
||||||
.withMessage('Votre nom est trop long')
|
.withMessage("Votre nom est trop long")
|
||||||
.custom(async name => {
|
.custom(async (name) => {
|
||||||
try {
|
try {
|
||||||
const user = await Users.findOne({ where: { name } })
|
const user = await Users.findOne({ where: { name } });
|
||||||
if (user) {
|
if (user) {
|
||||||
return Promise.reject(new Error('Le nom existe déjà...'))
|
return Promise.reject("Le nom existe déjà...");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error);
|
||||||
}
|
}
|
||||||
return true
|
return true;
|
||||||
})
|
})
|
||||||
],
|
], usersController.register);
|
||||||
usersController.register
|
|
||||||
)
|
|
||||||
|
|
||||||
// Confirme l'inscription
|
// Confirme l'inscription
|
||||||
UsersRouter.get('/confirm-email/:tempToken', usersController.confirmEmail)
|
UsersRouter.get('/confirm-email/:tempToken', usersController.confirmEmail);
|
||||||
|
|
||||||
UsersRouter.route('/reset-password')
|
UsersRouter.route('/reset-password')
|
||||||
|
|
||||||
// Demande une réinitialisation du mot de passe
|
// Demande une réinitialisation du mot de passe
|
||||||
.post(
|
.post([
|
||||||
[
|
|
||||||
body('email')
|
body('email')
|
||||||
.isEmail()
|
.isEmail()
|
||||||
.withMessage('Veuillez rentré une adresse mail valide.')
|
.withMessage("Veuillez rentré une adresse mail valide.")
|
||||||
],
|
], usersController.resetPassword)
|
||||||
usersController.resetPassword
|
|
||||||
)
|
|
||||||
|
|
||||||
// Nouveau mot de passe
|
// Nouveau mot de passe
|
||||||
.put(
|
.put([
|
||||||
[
|
|
||||||
body('password')
|
body('password')
|
||||||
.isLength({ min: 4 })
|
.isLength({ min: 4 })
|
||||||
.withMessage('Votre mot de passe est trop court!')
|
.withMessage("Votre mot de passe est trop court!")
|
||||||
],
|
], usersController.newPassword);
|
||||||
usersController.newPassword
|
|
||||||
)
|
|
||||||
|
|
||||||
module.exports = UsersRouter
|
module.exports = UsersRouter;
|
@ -1,73 +0,0 @@
|
|||||||
version: '3.0'
|
|
||||||
services:
|
|
||||||
functionproject-api:
|
|
||||||
build:
|
|
||||||
context: './api'
|
|
||||||
ports:
|
|
||||||
- '8080:8080'
|
|
||||||
depends_on:
|
|
||||||
- 'functionproject-database'
|
|
||||||
- 'functionproject-maildev'
|
|
||||||
volumes:
|
|
||||||
- './api:/app'
|
|
||||||
- '/app/node_modules'
|
|
||||||
environment:
|
|
||||||
WAIT_HOSTS: 'functionproject-database:3306'
|
|
||||||
container_name: 'functionproject-api'
|
|
||||||
|
|
||||||
s.divlo.fr-website:
|
|
||||||
build:
|
|
||||||
context: './s.divlo.fr'
|
|
||||||
ports:
|
|
||||||
- '7000:7000'
|
|
||||||
depends_on:
|
|
||||||
- 'functionproject-database'
|
|
||||||
volumes:
|
|
||||||
- './s.divlo.fr:/app'
|
|
||||||
- '/app/node_modules'
|
|
||||||
environment:
|
|
||||||
WAIT_HOSTS: 'functionproject-database:3306'
|
|
||||||
container_name: 's.divlo.fr-website'
|
|
||||||
|
|
||||||
functionproject-website:
|
|
||||||
build:
|
|
||||||
context: './website'
|
|
||||||
ports:
|
|
||||||
- '3000:3000'
|
|
||||||
volumes:
|
|
||||||
- './website:/app'
|
|
||||||
- '/app/node_modules'
|
|
||||||
container_name: 'functionproject-website'
|
|
||||||
|
|
||||||
functionproject-phpmyadmin:
|
|
||||||
image: 'phpmyadmin/phpmyadmin:5.1.0'
|
|
||||||
environment:
|
|
||||||
PMA_HOST: 'functionproject-database'
|
|
||||||
PMA_USER: 'root'
|
|
||||||
PMA_PASSWORD: 'password'
|
|
||||||
ports:
|
|
||||||
- '8000:80'
|
|
||||||
depends_on:
|
|
||||||
- 'functionproject-database'
|
|
||||||
container_name: 'functionproject-phpmyadmin'
|
|
||||||
|
|
||||||
functionproject-database:
|
|
||||||
image: 'mysql:8.0.23'
|
|
||||||
command: '--default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci'
|
|
||||||
environment:
|
|
||||||
MYSQL_ROOT_PASSWORD: 'password'
|
|
||||||
MYSQL_DATABASE: 'functionproject'
|
|
||||||
ports:
|
|
||||||
- '3306:3306'
|
|
||||||
volumes:
|
|
||||||
- 'database-volume:/var/lib/mysql'
|
|
||||||
container_name: 'functionproject-database'
|
|
||||||
|
|
||||||
functionproject-maildev:
|
|
||||||
image: 'maildev/maildev:1.1.0'
|
|
||||||
ports:
|
|
||||||
- '1080:80'
|
|
||||||
container_name: 'functionproject-maildev'
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
database-volume:
|
|
@ -1,2 +0,0 @@
|
|||||||
node_modules
|
|
||||||
build
|
|
@ -1,6 +0,0 @@
|
|||||||
COMPOSE_PROJECT_NAME="s.divlo.fr-website"
|
|
||||||
DATABASE_HOST="functionproject-database"
|
|
||||||
DATABASE_NAME="functionproject"
|
|
||||||
DATABASE_USER="root"
|
|
||||||
DATABASE_PASSWORD="password"
|
|
||||||
DATABASE_PORT=3306
|
|