Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • web-et-numerique/factory/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server
1 result
Show changes
Commits on Source (87)
Showing
with 3544 additions and 5434 deletions
stages:
- quality
- test
- quality
- build
- deploy
......@@ -8,9 +8,6 @@ default:
services:
- name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:18.09-dind
alias: docker
- name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/elasticsearch:7.16.2
alias: elasticsearch
command: ['bin/elasticsearch', '-Expack.security.enabled=false', '-Ediscovery.type=single-node']
variables:
DEPENDENCY_PROXY: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/
......@@ -39,6 +36,7 @@ build_branch:
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:18.09
stage: build
only:
- V2.0
- merge_requests
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
......@@ -51,8 +49,6 @@ build-release:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:18.09
services:
- ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/:18.09-dind
stage: build
only:
- tags
......@@ -67,6 +63,7 @@ deploy_dev:
- deploy
only:
- dev
- V2.0
script:
- cd /home/mps/ram
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
......
## Description du problème
_Donnez une briève description du problème_
## L'environnement
#### Utilisez vous l'application sur :
- [ ] Mobile
- [ ] Ordinateur
##### En cas de mobile
###### Quel type de mobile utilisez-vous?
- [ ] Android
- [ ] Iphone
###### Quel navigateur utilisez-vous?
- [ ] Chrome
- [ ] Safari
- [ ] Autre
##### En cas d'ordinateur
###### Quel navigateur utilisez-vous?
- [ ] Chrome
- [ ] Firefox
- [ ] Safari
- [ ] Autre
## Le bug
#### Quelles sont les étapes qui ont menées au problème?
_Donnez une description des étapes, il est fortemment conseillé de l'accompagner par des captures d'écran_
#### Quel est le comportement obtenu?
_Donnez une description du comportement obtenu, il est fortemment conseillé de l'accompagner par des captures d'écran_
#### Quel est le comportement attendu?
_Donnez une description du comportement attendu_
| :triangular_flag_on_post: Give your MR the same name that the desired squash commit. In doubt, check the conventional commit [doc](https://www.conventionalcommits.org/en/v1.0.0/).|
| --- |
## What does this MR do and why?
_Describe in detail what your merge request does and why._
| :warning: Keep an up to date checklist based on your icescrum tasks during all the draft phase to help any other developer who would take the job after you to finish it. |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| :warning: Keep an up to date checklist based on your icescrum tasks during all the draft phase of the MR to help any other developer who would take the job after you to finish it.|
| --- |
## Screenshots or screen recordings
_These are strongly recommended to assist reviewers and reduce the time to merge your change._
## How to set up and validate locally (or on alpha)
_List all steps to set up and validate the changes on local environment._
## MR acceptance checklist
_To be completed by the chosen reviewer._
<!---
......@@ -25,11 +27,12 @@ More reading on checklists can be found in the "Checklist Manifesto": http://atu
"It is common to misconceive how checklists function in complex lines of work. They are not comprehensive how-to guides, whether for building a skyscraper or getting a plane out of trouble. They are quick and simple tools aimed to buttress the skills of expert professionals." - Gawande, Atul. The Checklist Manifesto
--->
### Quality
- [ ] Confirmed
### Quality [![Bugs](https://sonarqube.forge.grandlyon.com/api/project_badges/measure?project=ram_server&metric=bugs&token=ac7a374a553a3aa458e5b538ce1a85c4fba146fb)](https://sonarqube.forge.grandlyon.com/dashboard?id=ram_server) - [![Code Smells](https://sonarqube.forge.grandlyon.com/api/project_badges/measure?project=ram_server&metric=code_smells&token=ac7a374a553a3aa458e5b538ce1a85c4fba146fb)](https://sonarqube.forge.grandlyon.com/dashboard?id=ram_server)
* [ ] Confirmed
1. For the code that this change impacts, I believe that the automated tests validate functionality that is highly important to users. If the existing automated tests do not cover this functionality, I have added the necessary additional tests or I have added an issue to describe the automation testing gap and linked it to this MR.
1. For the code that this change impacts, I believe that the automated tests validate functionality that is highly important to users. If the existing automated tests do not cover this functionality, I have added the necessary additional tests or I have added an issue to describe the automation testing gap and linked it to this MR.
1. I have made sure that the sonar quality coverage is up to standards.
1. I have considered the impact of this change on the front-end, back-end, and database portions of the system where appropriate and applied.
1. I have tested this MR in all supported browsers or determined that this testing is not needed.
......@@ -37,26 +40,26 @@ More reading on checklists can be found in the "Checklist Manifesto": http://atu
### Performance, reliability and availability
- [ ] Confirmed
* [ ] Confirmed
1. I am confident that this MR does not harm performance, or I have asked a reviewer to help assess the performance impact.
1. I have considered the scalability risk based on future predicted growth.
### Documentation
- [ ] Confirmed
* [ ] Confirmed
1. I have prepared a squash commit to feed the changelog linked to the current milestone.
1. The MR is named after the desired squash commit to feed the changelog linked to the current milestone.
1. I have added/updated documentation (also updated if the changes feature a deprecation) or I have decided that documentation changes are not needed for this MR.
### Security
### Security [![Security Rating](https://sonarqube.forge.grandlyon.com/api/project_badges/measure?project=ram_server&metric=security_rating&token=ac7a374a553a3aa458e5b538ce1a85c4fba146fb)](https://sonarqube.forge.grandlyon.com/dashboard?id=ram_server)
- [ ] Confirmed
* [ ] Confirmed
1. I have confirmed that if this MR does not contains any sensitive informations hidden in the changes.
### Deployment
- [ ] Confirmed
* [ ] Confirmed
1. When featured on a self-data project release, i have made sure my app version in the manifest and package.json is incremented and any relative changes to the permissions are clearly written and transmitted to Cozy.
......@@ -2,6 +2,112 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [2.0.0-beta3](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v1.17.0...v2.0.0-beta3) (2022-10-03)
### Features
* **annuaire:** Add userRegistry endpoint for research ([b19bbf3](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/b19bbf3dcb1e1dc699b023642ed243e62b74dd6c))
* **newsletter:** implementation of mailchimp ([b7f300f](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/b7f300fd8c108ad9205d446d960694c52872b328))
* patch unique property of a structure US162 ([c01dca0](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/c01dca0992f3d982b6037cce6b930b9711917ba3))
* **profile:** add structure owners screen ([5d4002d](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/5d4002dd3d8b1f1557fc42dac8d4283723821399))
* **profile:** logged in users can access the profile of other users ([e717cdc](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/e717cdcae246e7af56e9602a23c3390807e6097b))
* structure mail notification reset and new handling ([a039487](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/a039487316c7af1e4a57d4f3417bc59637d55993))
* **structure:** remove useless await ([f657205](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/f65720593f6657036f07530aa0dcbccd98ec1547))
* **structure:** remove useless server lockdown filter ([41a5d80](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/41a5d8024e5a3f957a271625208bb9c481a5a6e8))
### Bug Fixes
* **annuaire:** Fix case one job an no employer for user ([9600225](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/9600225645b2b6ccfeb5aa487e58a38c6e7cd93d))
* **annuaire:** Remove unverified users from list ([c234fe0](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/c234fe09f2c73d566a50b886d38c1a094f0774a5))
* **cicd:** update V2.0 job ([b18cb37](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/b18cb376f25acff6cef26e88bb8c0b7c9656b4e7))
* **deps:** update dependency passport to ^0.6.0 ([cfd143c](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/cfd143c813d800166637ff7f375eca4d5aff1ec4))
* **init:** accompanements order ([9c2efce](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/9c2efce483b02d322cec26630459029526c587c7))
* release build issue ([1d551d8](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/1d551d8618c74d0c9ece8f0613df280cf6586927))
* **search:** add java option to limit es ram use ([25b2529](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/25b2529a056427744352521c5e026ad2c45ef0dd))
* **structureDto:** phone number is now optional ([36a32ad](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/36a32adfb0157eab551ec47b5fda48e04b49d86e))
## [2.0.0-beta2](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v2.0.0-beta1.1...v2.0.0-beta2) (2022-05-24)
### Features
* **admin:** administration panel for jobs and employers ([7ed53e7](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/7ed53e756546b424248f004cf7af9da558a1a434))
* **edit-profile:** edit profile page ([23bde5d](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/23bde5dbcd50620fc946c7663518040b92ee8c48))
* **structure:** Get more info about structure owner details ([08f9c75](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/08f9c7539af7dc93d25fb7c97f8320b95f62b618))
### Bug Fixes
* auth issue with reading env var ([f46b600](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/f46b6003f87ad808a15bf174ff22059b9c9c52f3))
* **dependencies:** update minor version to fix vulnerabilities ([629eeab](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/629eeabd8e3f7ddbdf503027059ad69282a2f925))
* **deps:** update dependency class-validator to ^0.13.0 ([95f7189](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/95f71895ff46ea8bfb2f98f55e4753159a504239))
* elastic unit test ([641e484](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/641e4849ccf324efaa64ba0e164753709361b2d2))
## [2.0.0-beta1.1](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v2.0.0-beta1...v2.0.0-beta1.1) (2022-04-04)
### Bug Fixes
* **structures:** fix structure création issue for equipments and userverification ([f46d545](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/f46d54551a34476e2d320492c58347bb4cb3c90c))
## [2.0.0-beta1](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v1.16.0...v2.0.0-beta1) (2022-03-29)
### Features
* **jobs:** add filtering of unvalidated jobs ([2d98fc6](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/2d98fc6689d5759c8affda3183a7fffe10c3be55))
* **onboarding:** add structure search by name with improved french analyzer ([b0d2e9b](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/b0d2e9b555409a5c07857939ab2bab969354c90b))
* **personalOffers:** create personal offers endpoints ([ba6f7db](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/ba6f7dbd7faf31ebb00177cc6ed78f02fa1d387f))
### Bug Fixes
* **gitlab-ci:** update V2.0 autodeploy ([17b77c7](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/17b77c72541b2932b37658e232dd9dc631728e30))
* **swagger:** routing definition ([d264a4e](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/d264a4eedda9253e46300ba2fee8bcb9289be086))
## [2.0.0-beta2](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v2.0.0-beta1.1...v2.0.0-beta2) (2022-05-24)
### Features
* **admin:** administration panel for jobs and employers ([7ed53e7](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/7ed53e756546b424248f004cf7af9da558a1a434))
* **admin:** now display last update date next to structure names ([01d5665](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/01d56659ebd323105dcfa46a9bbb929e482fc05c))
* **digital helps:** rename "Accompagnement CAF" to "CAF" ([90e106f](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/90e106f572ea52d990a67b49f00fe434965cc083))
* **edit-profile:** edit profile page ([23bde5d](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/23bde5dbcd50620fc946c7663518040b92ee8c48))
* **structure:** Get more info about structure owner details ([08f9c75](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/08f9c7539af7dc93d25fb7c97f8320b95f62b618))
### Bug Fixes
* auth issue with reading env var ([f46b600](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/f46b6003f87ad808a15bf174ff22059b9c9c52f3))
* **dependencies:** update minor version to fix vulnerabilities ([629eeab](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/629eeabd8e3f7ddbdf503027059ad69282a2f925))
* **deps:** update dependency class-validator to ^0.13.0 ([95f7189](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/95f71895ff46ea8bfb2f98f55e4753159a504239))
* elastic unit test ([641e484](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/641e4849ccf324efaa64ba0e164753709361b2d2))
* Resolve "Join validation issue for admin" and refactor of string to date for structure updatedAt and createdAt ([df74738](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/df747380f58b5f093265c185b357e666792c04a9))
* sonar ([a222df2](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/a222df249f85d780e31f24e79d52431f4eada6b4))
## [2.0.0-beta1.1](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v2.0.0-beta1...v2.0.0-beta1.1) (2022-04-04)
### Bug Fixes
* **structures:** fix structure création issue for equipments and userverification ([f46d545](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/f46d54551a34476e2d320492c58347bb4cb3c90c))
## [2.0.0-beta1](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v1.16.0...v2.0.0-beta1) (2022-03-29)
### Features
* **jobs:** add filtering of unvalidated jobs ([2d98fc6](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/2d98fc6689d5759c8affda3183a7fffe10c3be55))
* **onboarding:** add structure search by name with improved french analyzer ([b0d2e9b](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/b0d2e9b555409a5c07857939ab2bab969354c90b))
* **personalOffers:** create personal offers endpoints ([ba6f7db](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/ba6f7dbd7faf31ebb00177cc6ed78f02fa1d387f))
### Bug Fixes
* **gitlab-ci:** update V2.0 autodeploy ([17b77c7](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/17b77c72541b2932b37658e232dd9dc631728e30))
* **swagger:** routing definition ([d264a4e](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/d264a4eedda9253e46300ba2fee8bcb9289be086))
## [1.17.0](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v1.16.0...v1.17.0) (2022-05-30)
......
FROM node:12.13-slim
FROM node:14.20-slim
# Create app directory
WORKDIR /app
......
......@@ -4,7 +4,7 @@
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
[circleci-url]: https://circleci.com/gh/nestjs/nest
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
<p align="center">
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
......@@ -47,7 +47,6 @@ $ npm install
### Base de donnée
```bash
$ docker-compose up -d database-ram
$ docker-compose up -d mongo-express
......@@ -70,17 +69,20 @@ $ npm run start:prod
```bash
# Lien vers le swagger
$ http://localhost:3000/api
$ http://localhost:3000/doc
# Lien vers le mongo-express
$ http://localhost:8081
```
## Documentation
## Documentation
A documentation is generated with compodoc in addition of the existing documentation on the wiki.
```sh
npm run doc:serve
```
You can now visualize it at : `localhost:8080`
## Test
......
......@@ -106,6 +106,7 @@ services:
discovery.type: single-node
xpack.security.enabled: ${ELASTIC_SECURITY}
ELASTIC_PASSWORD: ${ELASTICSEARCH_PASSWORD}
ES_JAVA_OPTS: '-Xms512m -Xmx512m'
volumes:
- db-elastic:/usr/share/elasticsearch/data
networks:
......@@ -113,22 +114,6 @@ services:
ports:
- ${ELASTICSEARCH_PORT}:9200
kib01:
image: docker.elastic.co/kibana/kibana:7.6.1
restart: unless-stopped
container_name: resin-kib
ports:
- ${KIBANA_PORT}:5601
environment:
ELASTICSEARCH_URL: http://es01:9200
ELASTICSEARCH_HOSTS: '["http://es01:9200"]'
ELASTICSEARCH_USERNAME: elastic
ELASTICSEARCH_PASSWORD: ${ELASTICSEARCH_PASSWORD}
depends_on:
- es01
networks:
- elastic
volumes:
db-ram:
driver: local
......
This diff is collapsed.
{
"name": "ram_server",
"private": true,
"version": "1.17.0",
"version": "2.0.0-beta3",
"description": "Nest TypeScript starter repository",
"license": "MIT",
"scripts": {
......@@ -17,8 +17,8 @@
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"release": "standard-version",
"init-db": "node ./scripts/init-db.js",
"test": "jest",
"test:watch": "jest --config ./test/jest.json --watch",
"test": "jest --config ./test/jest.json --coverage",
"test:watch": "jest --config ./test/jest.json --watch --coverage",
"test:cov": "jest --config ./test/jest.json --coverage --ci --reporters=default --reporters=jest-junit",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json",
......@@ -28,28 +28,31 @@
},
"dependencies": {
"@elastic/elasticsearch": "^7.12.0",
"@nestjs/common": "^7.6.13",
"@mailchimp/mailchimp_marketing": "^3.0.78",
"@nestjs/axios": "^0.1.0",
"@nestjs/common": "^9.0.11",
"@nestjs/config": "^0.6.3",
"@nestjs/core": "^7.5.1",
"@nestjs/core": "^9.0.11",
"@nestjs/elasticsearch": "^7.1.0",
"@nestjs/jwt": "^7.2.0",
"@nestjs/mongoose": "^7.1.0",
"@nestjs/passport": "^7.1.5",
"@nestjs/platform-express": "^7.5.1",
"@nestjs/platform-express": "^9.0.11",
"@nestjs/schedule": "^0.4.1",
"@nestjs/swagger": "^4.7.5",
"@nestjs/swagger": "^6.1.2",
"@tryghost/admin-api": "^1.4.4",
"@types/bcrypt": "^3.0.0",
"axios": "^0.27.2",
"bcrypt": "^5.0.1",
"class-transformer": "^0.3.1",
"class-validator": "^0.12.2",
"class-validator": "^0.13.0",
"dotenv": "^8.2.0",
"ejs": "^3.1.6",
"ejs": "^3.1.7",
"form-data": "^3.0.0",
"luxon": "^1.25.0",
"migrate": "^1.7.0",
"mongoose": "^5.10.15",
"passport": "^0.4.1",
"passport": "^0.6.0",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"reflect-metadata": "^0.1.13",
......@@ -62,28 +65,28 @@
"devDependencies": {
"@compodoc/compodoc": "^1.1.16",
"@golevelup/ts-jest": "^0.3.2",
"@nestjs/cli": "^7.5.1",
"@nestjs/schematics": "^7.1.3",
"@nestjs/testing": "^7.5.1",
"@nestjs/cli": "^9.1.3",
"@nestjs/schematics": "^9.0.3",
"@nestjs/testing": "^9.0.11",
"@types/express": "^4.17.8",
"@types/jest": "^26.0.15",
"@types/mongoose": "^5.10.1",
"@types/node": "^14.14.6",
"@types/passport-local": "^1.0.33",
"@types/supertest": "^2.0.10",
"@typescript-eslint/eslint-plugin": "^4.6.1",
"@typescript-eslint/parser": "^4.6.1",
"eslint": "^7.12.1",
"@typescript-eslint/eslint-plugin": "^5.37",
"@typescript-eslint/parser": "^5.37",
"eslint": "^8.0.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^26.6.3",
"jest-junit": "^12.0.0",
"jest-junit": "^14.0.0",
"nodemon": "^2.0.6",
"prettier": "^2.1.2",
"supertest": "^6.0.0",
"ts-jest": "^26.4.3",
"ts-loader": "^8.0.8",
"ts-node": "^9.0.0",
"ts-node": "^10.9.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.0.5"
},
......
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>systemes-dinformation/renovate/renovate-config"
]
}
......@@ -8,16 +8,20 @@ module.exports = {
modules: [
{
id: 'accompagnantCaf',
text: 'Accompagnant CAF',
text: 'CAF',
},
{
id: 'poleEmploi',
text: 'Pôle Emploi',
id: 'carsat',
text: 'CARSAT',
},
{
id: 'cpam',
text: 'CPAM',
},
{
id: 'demarcheMetropolitaine',
text: 'Démarches Métropolitaines',
},
{
id: 'impots',
text: 'Impôts',
......@@ -27,12 +31,8 @@ module.exports = {
text: 'Logement',
},
{
id: 'carsat',
text: 'CARSAT',
},
{
id: 'demarcheMetropolitaine',
text: 'Démarches Métropolitaines',
id: 'poleEmploi',
text: 'Pôle Emploi',
},
{
id: 'autres',
......
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mongoose = require('mongoose');
module.exports = {
data: [
{
_id: mongoose.Types.ObjectId('6285289d02c9259438c802d3'),
name: 'Association',
validated: true,
},
{
_id: mongoose.Types.ObjectId('62867faf7a5b13480c22b2fc'),
name: 'CAF',
validated: true,
},
{
_id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac3'),
name: 'CARSAT',
validated: true,
},
{
_id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac4'),
name: 'CCAS',
validated: true,
},
{
_id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac5'),
name: 'CPAM',
validated: true,
},
{
_id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac6'),
name: 'Centre socio-culturel',
validated: true,
},
{
_id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac7'),
name: 'Cyberbase',
validated: true,
},
{
_id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac8'),
name: 'Espace de coworking',
validated: true,
},
{
_id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac9'),
name: 'Fablab',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca830'),
name: 'MJC',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca831'),
name: 'Mairie',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca832'),
name: 'Maison France Service',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca833'),
name: 'Missions locales',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca834'),
name: 'Médiathèque / Bibliothèque',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
name: 'Métropole de Lyon',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca836'),
name: 'Pimms',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca837'),
name: 'Pôle emploi',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca838'),
name: 'Ressourcerie',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca839'),
name: "Structure d'insertion",
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca83a'),
name: 'Structure de formation',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca83b'),
name: 'Structure information jeunesse (SIJ)',
validated: true,
},
],
};
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mongoose = require('mongoose');
module.exports = {
data: [
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca845'),
hasPersonalOffer: true,
name: 'Formateur',
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
name: 'CNFS',
hasPersonalOffer: true,
validated: true,
},
{
_id: mongoose.Types.ObjectId('627b6ca899862168705ca847'),
hasPersonalOffer: true,
name: 'Médiateur numérique',
validated: true,
},
{
hasPersonalOffer: false,
_id: mongoose.Types.ObjectId('627b6ca899862168705ca848'),
name: 'Travailleur social',
validated: true,
},
{
hasPersonalOffer: false,
_id: mongoose.Types.ObjectId('627b6ca899862168705ca849'),
name: 'Conseiller',
validated: true,
},
{
hasPersonalOffer: false,
_id: mongoose.Types.ObjectId('627b6ca899862168705ca84a'),
name: 'Chef de projet',
validated: true,
},
{
hasPersonalOffer: false,
_id: mongoose.Types.ObjectId('6283603c51d1098fd4a8facf'),
name: 'Élu',
validated: true,
},
],
};
......@@ -45,7 +45,7 @@ module.exports = {
time: [
{
closing: '12:00',
opening: '9:00',
opening: '09:00',
},
{
closing: '17:30',
......@@ -71,7 +71,7 @@ module.exports = {
time: [
{
closing: '12:00',
opening: '9:00',
opening: '09:00',
},
{
closing: '17:30',
......@@ -84,7 +84,7 @@ module.exports = {
time: [
{
closing: '12:00',
opening: '9:00',
opening: '09:00',
},
{
closing: '17:30',
......@@ -97,7 +97,7 @@ module.exports = {
time: [
{
closing: '12:00',
opening: '9:00',
opening: '09:00',
},
],
},
......@@ -367,7 +367,7 @@ module.exports = {
time: [
{
closing: '12:30',
opening: '9:00',
opening: '09:00',
},
{
closing: '17:00',
......@@ -380,7 +380,7 @@ module.exports = {
time: [
{
closing: '12:30',
opening: '9:00',
opening: '09:00',
},
{
closing: '17:00',
......@@ -393,7 +393,7 @@ module.exports = {
time: [
{
closing: '12:30',
opening: '9:00',
opening: '09:00',
},
{
closing: '17:00',
......@@ -406,7 +406,7 @@ module.exports = {
time: [
{
closing: '12:30',
opening: '9:00',
opening: '09:00',
},
{
closing: '17:00',
......@@ -419,7 +419,7 @@ module.exports = {
time: [
{
closing: '12:30',
opening: '9:00',
opening: '09:00',
},
],
},
......@@ -698,7 +698,7 @@ module.exports = {
time: [
{
closing: '17:00',
opening: '9:00',
opening: '09:00',
},
],
},
......@@ -707,7 +707,7 @@ module.exports = {
time: [
{
closing: '17:00',
opening: '9:00',
opening: '09:00',
},
],
},
......@@ -716,7 +716,7 @@ module.exports = {
time: [
{
closing: '17:00',
opening: '9:00',
opening: '09:00',
},
],
},
......@@ -725,7 +725,7 @@ module.exports = {
time: [
{
closing: '17:00',
opening: '9:00',
opening: '09:00',
},
],
},
......@@ -734,7 +734,7 @@ module.exports = {
time: [
{
closing: '17:00',
opening: '9:00',
opening: '09:00',
},
],
},
......
......@@ -17,6 +17,8 @@ module.exports = {
emailVerified: true,
email: 'admin@admin.com',
structureOutdatedMailSent: [],
employer: mongoose.Types.ObjectId('627b6ca899862168705ca836'),
job: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
},
{
structureOutdatedMailSent: [],
......@@ -28,10 +30,12 @@ module.exports = {
resetPasswordToken: null,
validationToken: null,
emailVerified: true,
email: 'paula.dubois@mii.com',
email: 'paula.dubois@test.com',
name: 'Paula',
surname: 'DUBOIS',
phone: '06 07 08 09 10',
employer: mongoose.Types.ObjectId('627b6ca899862168705ca836'),
job: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
},
{
structureOutdatedMailSent: [],
......@@ -52,6 +56,128 @@ module.exports = {
name: 'Jean-Paul',
surname: 'DESCHAMPS',
phone: '06 11 11 11 11',
employer: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
job: mongoose.Types.ObjectId('627b6ca899862168705ca848'),
},
{
structureOutdatedMailSent: [],
pendingStructuresLink: [],
structuresLink: [
mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
],
newEmail: null,
changeEmailToken: null,
role: 0,
resetPasswordToken: null,
validationToken: null,
emailVerified: true,
email: 'marine.ducanal@test.com',
name: 'Marine',
surname: 'DUCANAL',
phone: '06 11 11 11 11',
employer: mongoose.Types.ObjectId('627b6ca899862168705ca837'),
job: mongoose.Types.ObjectId('627b6ca899862168705ca848'),
},
{
structureOutdatedMailSent: [],
pendingStructuresLink: [],
structuresLink: [
mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
],
newEmail: null,
changeEmailToken: null,
role: 0,
resetPasswordToken: null,
validationToken: null,
emailVerified: true,
email: 'hugo.nouts@test.com',
name: 'Hugo',
surname: 'NOUTS',
phone: '06 11 11 11 11',
employer: mongoose.Types.ObjectId('627b6ca899862168705ca833'),
job: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
},
{
structureOutdatedMailSent: [],
pendingStructuresLink: [],
structuresLink: [
mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
],
newEmail: null,
changeEmailToken: null,
role: 0,
resetPasswordToken: null,
validationToken: null,
emailVerified: true,
email: 'bastien.dumont@test.com',
name: 'Bastien',
surname: 'DUMONT',
phone: '06 11 11 11 11',
employer: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
job: mongoose.Types.ObjectId('627b6ca899862168705ca849'),
},
{
structureOutdatedMailSent: [],
pendingStructuresLink: [],
structuresLink: [
mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
],
newEmail: null,
changeEmailToken: null,
role: 0,
resetPasswordToken: null,
validationToken: null,
emailVerified: true,
email: 'guilhem.carron@test.com',
name: 'Guilhem',
surname: 'CARRON',
phone: '06 11 11 11 11',
employer: mongoose.Types.ObjectId('627b6ca899862168705ca834'),
job: mongoose.Types.ObjectId('627b6ca899862168705ca848'),
},
{
structureOutdatedMailSent: [],
pendingStructuresLink: [],
structuresLink: [
mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
],
newEmail: null,
changeEmailToken: null,
role: 0,
resetPasswordToken: null,
validationToken: null,
emailVerified: true,
email: 'hugo.subtil@test.com',
name: 'Hugo',
surname: 'SUBTIL',
phone: '06 11 11 11 11',
employer: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
job: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
},
{
structureOutdatedMailSent: [],
pendingStructuresLink: [],
structuresLink: [
mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
],
newEmail: null,
changeEmailToken: null,
role: 0,
resetPasswordToken: null,
validationToken: null,
emailVerified: true,
email: 'remi.pailharey@test.com',
name: 'Rémi',
surname: 'PAILHAREY',
phone: '06 11 11 11 11',
employer: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
job: mongoose.Types.ObjectId('627b6ca899862168705ca845'),
},
],
};
/* eslint-disable @typescript-eslint/no-var-requires */
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mongoose = require('mongoose');
// eslint-disable-next-line @typescript-eslint/no-var-requires
......@@ -7,6 +8,8 @@ const categoriesOthersData = require('./data/categoriesOthers');
const categoriesAccompanementsData = require('./data/categoriesAccompanements');
const categoriesFormationData = require('./data/categoriesFormation');
const structuresData = require('./data/structures');
const jobsData = require('./data/jobs');
const employersData = require('./data/employers');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const bcrypt = require('bcrypt');
// eslint-disable-next-line @typescript-eslint/no-var-requires
......@@ -40,8 +43,9 @@ const handleError = async (name, err) => {
else throw err;
} else console.log(`-- ${name} collection dropped --`);
};
// define Schema
var usersSchema = mongoose.Schema({
const usersSchema = mongoose.Schema({
name: String,
surname: String,
email: String,
......@@ -56,30 +60,50 @@ var usersSchema = mongoose.Schema({
pendingStructuresLink: [],
password: String,
phone: String,
employer: String,
job: String,
});
var structuresTypeSchema = mongoose.Schema(
const jobsSchema = mongoose.Schema(
{
name: String,
hasPersonalOffer: Boolean,
validated: Boolean,
},
{ collection: 'jobs' }
);
const employersSchema = mongoose.Schema(
{
name: String,
validated: Boolean,
},
{ collection: 'employers' }
);
const structuresTypeSchema = mongoose.Schema(
{
name: String,
values: [],
},
{ collection: 'structuretype' }
);
var categoriesOthersSchema = mongoose.Schema({
const categoriesOthersSchema = mongoose.Schema({
name: String,
id: String,
modules: [],
});
var categoriesAccompanementsSchema = mongoose.Schema({
const categoriesAccompanementsSchema = mongoose.Schema({
name: String,
id: String,
modules: [],
});
var categoriesFormationSchema = mongoose.Schema({
const categoriesFormationSchema = mongoose.Schema({
name: String,
id: String,
modules: [],
});
var structuresSchema = mongoose.Schema({
const structuresSchema = mongoose.Schema({
numero: String,
createdAt: String,
updatedAt: String,
......@@ -123,12 +147,14 @@ var structuresSchema = mongoose.Schema({
});
// compile schema to model
var User = mongoose.model('Users', usersSchema);
var structuresType = mongoose.model('structureType', structuresTypeSchema);
var categoriesOthers = mongoose.model('categoriesOthers', categoriesOthersSchema);
var categoriesAccompanements = mongoose.model('CategoriesAccompagnement', categoriesAccompanementsSchema);
var categoriesFormation = mongoose.model('categoriesFormation', categoriesFormationSchema);
var structures = mongoose.model('structures', structuresSchema);
const user = mongoose.model('users', usersSchema);
const structuresType = mongoose.model('structureType', structuresTypeSchema);
const categoriesOthers = mongoose.model('categoriesOthers', categoriesOthersSchema);
const categoriesAccompanements = mongoose.model('CategoriesAccompagnement', categoriesAccompanementsSchema);
const categoriesFormation = mongoose.model('categoriesFormation', categoriesFormationSchema);
const structures = mongoose.model('structures', structuresSchema);
const jobs = mongoose.model('jobs', jobsSchema);
const employers = mongoose.model('employers', employersSchema);
/* drop users collections */
mongoose.connection.dropCollection('users', async (err) => {
......@@ -140,7 +166,7 @@ mongoose.connection.dropCollection('users', async (err) => {
user.password = hashPassword();
});
// save model to database
User.create(userData.data, function (error, user) {
user.create(userData.data, (error) => {
if (error) return console.error(error);
console.log('-- Users collection initialized --');
});
......@@ -180,6 +206,20 @@ mongoose.connection.dropCollection('structures', async (err) => {
await handleError('structures', err);
structures.create(structuresData.data, (error) => {
if (error) return console.error(error);
});
});
/* Create structures */
mongoose.connection.dropCollection('jobs', async (err) => {
await handleError('jobs', err);
jobs.create(jobsData.data, (error) => {
if (error) return console.error(error);
});
});
/* Create structures */
mongoose.connection.dropCollection('employers', async (err) => {
await handleError('employers', err);
employers.create(employersData.data, (error) => {
if (error) return console.error(error);
process.exit(0);
});
});
......@@ -14,7 +14,25 @@ axios
axios
.post('http://localhost:3000/api/structures/resetSearchIndex', {}, config)
.then((res) => {
console.log(`statusCode: ${res.status}`);
console.log(`Structures | statusCode: ${res.status}`);
})
.catch((error) => {
console.error('Error in index create');
console.error(error);
});
axios
.post('http://localhost:3000/api/employer/searchIndex', {}, config)
.then((res) => {
console.log(`Employers | statusCode: ${res.status}`);
})
.catch((error) => {
console.error('Error in index create');
console.error(error);
});
axios
.post('http://localhost:3000/api/userRegistry/searchIndex', {}, config)
.then((res) => {
console.log(`Users | statusCode: ${res.status}`);
})
.catch((error) => {
console.error('Error in index create');
......
import { HttpModule } from '@nestjs/common';
import { HttpModule } from '@nestjs/axios';
import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import { Types } from 'mongoose';
import { mockJwtAuthGuard } from '../../test/mock/guards/jwt-auth.mock.guard';
import { mockRoleGuard } from '../../test/mock/guards/role.mock.guard';
import { NewsletterServiceMock } from '../../test/mock/services/newsletter.mock.service';
......@@ -17,12 +18,50 @@ import { StructuresSearchService } from '../structures/services/structures-searc
import { StructuresService } from '../structures/services/structures.service';
import { RolesGuard } from '../users/guards/roles.guard';
import { User } from '../users/schemas/user.schema';
import { UsersService } from '../users/users.service';
import { EmployerSearchService } from '../users/services/employer-search.service';
import { EmployerService } from '../users/services/employer.service';
import { JobsService } from '../users/services/jobs.service';
import { UsersService } from '../users/services/users.service';
import { AdminController } from './admin.controller';
import { AdminService } from './admin.service';
describe('AdminController', () => {
let controller: AdminController;
let userService: UsersService;
const mockEmployerSearchService = {
indexEmployer: jest.fn(),
search: jest.fn(),
dropIndex: jest.fn(),
createEmployerIndex: jest.fn(),
deleteIndex: jest.fn(),
};
const mockEmployerService = {
findOne: jest.fn(),
deleteOneId: jest.fn(),
findByName: jest.fn(),
findAllValidated: jest.fn(),
findAllUnvalidated: jest.fn(),
createEmployerFromAdmin: jest.fn(),
validate: jest.fn(),
update: jest.fn(),
mergeEmployer: jest.fn(),
deleteInvalidEmployer: jest.fn(),
};
const mockJobService = {
findOne: jest.fn(),
findByName: jest.fn(),
deleteOneId: jest.fn(),
findAll: jest.fn(),
findAllUnvalidated: jest.fn(),
createJobFromAdmin: jest.fn(),
validate: jest.fn(),
update: jest.fn(),
mergeJob: jest.fn(),
deleteInvalidJob: jest.fn(),
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
......@@ -46,6 +85,18 @@ describe('AdminController', () => {
},
StructuresSearchService,
MailerService,
{
provide: EmployerService,
useValue: mockEmployerService,
},
{
provide: JobsService,
useValue: mockJobService,
},
{
provide: EmployerSearchService,
useValue: mockEmployerSearchService,
},
{
provide: getModelToken('User'),
useValue: User,
......@@ -68,6 +119,7 @@ describe('AdminController', () => {
.compile();
controller = module.get<AdminController>(AdminController);
userService = module.get<UsersService>(UsersService);
});
it('should be defined', () => {
......@@ -153,6 +205,134 @@ describe('AdminController', () => {
});
});
describe('setUserEmployer', () => {
it('should set a new employer to the user', async () => {
const spyer = jest.spyOn(userService, 'updateUserEmployer');
const mockUserId = '6231aefe76598527c8d0b5bc';
const mockEmployer = {
_id: Types.ObjectId('6231aefe76598527c8d0b5ba'),
name: 'Sopra',
validated: true,
};
mockEmployerService.findOne.mockResolvedValueOnce(mockEmployer);
const reply = await controller.setUserEmployer({
userId: mockUserId,
employerId: String(mockEmployer._id),
});
expect(spyer).toBeCalledTimes(1);
expect(spyer).toBeCalledWith(mockUserId, mockEmployer);
expect(reply).toBeTruthy();
});
it('should not set a new employer to the user if the employer does not exist', async () => {
const spyer = jest.spyOn(userService, 'updateUserEmployer');
const mockUserId = '6231aefe76598527c8d0b5bc';
const mockEmployer = {
_id: Types.ObjectId('6231aefe76598527c8d0b5ba'),
name: 'Sopra',
validated: true,
};
mockEmployerService.findOne.mockResolvedValueOnce(null);
try {
await controller.setUserEmployer({
userId: mockUserId,
employerId: String(mockEmployer._id),
});
expect(true).toBe(false);
} catch (e) {
expect(spyer).toBeCalledTimes(0);
expect(e.message).toBe('Employer does not exist');
expect(e.status).toBe(400);
}
});
it('should not set a new employer to the user if the user does not exist', async () => {
const spyer = jest.spyOn(userService, 'updateUserEmployer');
const mockUserId = 'thisuserdoesnotexist';
const mockEmployer = {
_id: Types.ObjectId('6231aefe76598527c8d0b5ba'),
name: 'Sopra',
validated: true,
};
mockEmployerService.findOne.mockResolvedValueOnce(mockEmployer);
try {
await controller.setUserEmployer({
userId: mockUserId,
employerId: String(mockEmployer._id),
});
expect(true).toBe(false);
} catch (e) {
expect(spyer).toBeCalledTimes(0);
expect(e.message).toBe('User does not exist');
expect(e.status).toBe(400);
}
});
});
describe('setUserJob', () => {
it('should set a new job to the user', async () => {
const spyer = jest.spyOn(userService, 'updateUserJob');
const mockUserId = '6231aefe76598527c8d0b5bc';
const mockJob = {
_id: Types.ObjectId('6231aefe76598527c8d0b5ba'),
name: 'Toto',
validated: true,
};
mockJobService.findOne.mockResolvedValueOnce(mockJob);
const reply = await controller.setUserJob({
userId: mockUserId,
jobId: String(mockJob._id),
});
expect(spyer).toBeCalledTimes(1);
expect(spyer).toBeCalledWith(mockUserId, mockJob);
expect(reply).toBeTruthy();
});
it('should not set a new job to the user if the job does not exist', async () => {
const spyer = jest.spyOn(userService, 'updateUserJob');
const mockUserId = '6231aefe76598527c8d0b5bc';
const mockJob = {
_id: Types.ObjectId('6231aefe76598527c8d0b5ba'),
name: 'Dev',
validated: true,
};
mockJobService.findOne.mockResolvedValueOnce(null);
try {
await controller.setUserJob({
userId: mockUserId,
jobId: String(mockJob._id),
});
expect(true).toBe(false);
} catch (e) {
expect(spyer).toBeCalledTimes(0);
expect(e.message).toBe('Job does not exist');
expect(e.status).toBe(400);
}
});
it('should not set a new job to the user if the user does not exist', async () => {
const spyer = jest.spyOn(userService, 'updateUserJob');
const mockUserId = 'thisuserdoesntexist';
const mockJob = {
_id: Types.ObjectId('6231aefe76598527c8d0b5ba'),
name: 'Dev',
validated: true,
};
mockJobService.findOne.mockResolvedValueOnce(mockJob);
try {
await controller.setUserJob({
userId: mockUserId,
jobId: String(mockJob._id),
});
expect(true).toBe(false);
} catch (e) {
expect(spyer).toBeCalledTimes(0);
expect(e.message).toBe('User does not exist');
expect(e.status).toBe(400);
}
});
});
describe('Search user', () => {
it('should return all users, empty string', async () => {
expect((await controller.searchUsers({ searchString: '' })).length).toBe(2);
......@@ -169,7 +349,7 @@ describe('AdminController', () => {
});
});
describe('Search user newleetter subscription', () => {
describe('Search user newsletter subscription', () => {
it('should return all subscribed users, empty string', async () => {
expect((await controller.getNewsletterSubscriptions({ searchString: '' })).length).toBe(3);
});
......
......@@ -8,9 +8,10 @@ import {
Logger,
Param,
Post,
Put,
UseGuards,
} from '@nestjs/common';
import { ApiOperation, ApiParam } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger';
import { validate } from 'class-validator';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { NewsletterSubscription } from '../newsletter/newsletter-subscription.schema';
......@@ -20,16 +21,23 @@ import { StructuresService } from '../structures/services/structures.service';
import { Roles } from '../users/decorators/roles.decorator';
import { RolesGuard } from '../users/guards/roles.guard';
import { IUser } from '../users/interfaces/user.interface';
import { UsersService } from '../users/users.service';
import { EmployerService } from '../users/services/employer.service';
import { JobsService } from '../users/services/jobs.service';
import { UsersService } from '../users/services/users.service';
import { AdminService } from './admin.service';
import { PendingStructureDto } from './dto/pending-structure.dto';
import { SetUserEmployerDto } from './dto/set-user-employer.dto';
import { SetUserJobDto } from './dto/set-user-job.dto';
@ApiTags('admin')
@Controller('admin')
export class AdminController {
private readonly logger = new Logger(AdminController.name);
constructor(
private usersService: UsersService,
private structuresService: StructuresService,
private jobsService: JobsService,
private employerService: EmployerService,
private newsletterService: NewsletterService,
private adminService: AdminService
) {}
......@@ -37,7 +45,7 @@ export class AdminController {
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@Get('pendingStructures')
@ApiOperation({ description: 'Get pending structre for validation' })
@ApiOperation({ description: 'Get pending structures for validation' })
public async getPendingAttachments(): Promise<PendingStructureDto[]> {
const pendingStructure = await this.usersService.getPendingStructures();
return Promise.all(
......@@ -54,7 +62,7 @@ export class AdminController {
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@Get('adminStructuresList')
@ApiOperation({ description: 'Get pending structre for validation' })
@ApiOperation({ description: 'Get pending structures for validation' })
public async getAdminStructuresList(): Promise<any> {
this.logger.debug('getAdminStructuresList');
const structuresList = { claimed: [], inClaim: [], toClaim: [], incomplete: [] };
......@@ -177,6 +185,7 @@ export class AdminController {
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@Delete('user/:id')
@ApiBearerAuth('JWT')
@ApiParam({ name: 'id', type: String, required: true })
public async deleteUser(@Param() params) {
const user = await this.usersService.deleteOneId(params.id);
......@@ -192,6 +201,7 @@ export class AdminController {
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@ApiBearerAuth('JWT')
@Post('searchUsers')
public async searchUsers(@Body() searchString: { searchString: string }) {
if (searchString && searchString.searchString && searchString.searchString.length > 0)
......@@ -201,14 +211,29 @@ export class AdminController {
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@Get('getUnAttachedUsers')
@ApiBearerAuth('JWT')
@Get('unAttachedUsers')
public async findUnattachedUsers() {
return this.usersService.findAllUnattached();
return this.usersService.findAllUnattached().then((formatUsers) => {
return formatUsers.map((user) => {
return {
id: user._id,
createdAt: user.createdAt ? user.createdAt.toLocaleDateString() : '',
surname: user.surname,
name: user.name,
email: user.email,
phone: user.phone,
job: user.job,
employer: user.employer,
};
});
});
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@Get('getAttachedUsers')
@ApiBearerAuth('JWT')
@Get('attachedUsers')
public async findAttachedUsers() {
return this.usersService.findAllAttached().then(async (users: IUser[]) => {
return this.structuresService.getAllUserCompletedStructures(users);
......@@ -216,8 +241,9 @@ export class AdminController {
}
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiBearerAuth('JWT')
@Roles('admin')
@Get('getUnVerifiedUsers')
@Get('unVerifiedUsers')
public async findUnVerifiedUsers() {
return this.usersService.findAllUnVerified().then(async (users: IUser[]) => {
return this.structuresService.getAllUserCompletedStructures(users);
......@@ -226,6 +252,7 @@ export class AdminController {
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@ApiBearerAuth('JWT')
@Post('searchNewsletterSubscriptions')
public async getNewsletterSubscriptions(@Body() searchString: { searchString: string }) {
if (searchString && searchString.searchString && searchString.searchString.length > 0)
......@@ -235,6 +262,7 @@ export class AdminController {
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@ApiBearerAuth('JWT')
@Get('countNewsletterSubscriptions')
public async countNewsletterSubscriptions(): Promise<number> {
return this.newsletterService.countNewsletterSubscriptions();
......@@ -242,9 +270,60 @@ export class AdminController {
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@ApiBearerAuth('JWT')
@Delete('newsletterSubscription/:email')
@ApiParam({ name: 'email', type: String, required: true })
public async unsubscribeUserFromNewsletter(@Param() params): Promise<NewsletterSubscription> {
return this.newsletterService.newsletterUnsubscribe(params.email);
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@ApiBearerAuth('JWT')
@ApiOperation({ description: 'Set user job' })
@ApiResponse({ status: HttpStatus.OK, description: 'Return user profile' })
@ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'User does not exist' })
@ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'Job does not exist' })
@Put('setUserJob')
public async setUserJob(@Body() setUserJob: SetUserJobDto): Promise<IUser> {
this.logger.debug(`setUserJob`);
const jobDocument = await this.jobsService.findOne(setUserJob.jobId);
if (!jobDocument) {
this.logger.warn(`Job does not exist: ${setUserJob.jobId}`);
throw new HttpException('Job does not exist', HttpStatus.BAD_REQUEST);
}
const userDocument = await this.usersService.findById(setUserJob.userId);
if (!userDocument) {
this.logger.warn(`User does not exist: ${setUserJob.userId}`);
throw new HttpException('User does not exist', HttpStatus.BAD_REQUEST);
}
await this.usersService.updateUserJob(userDocument._id, jobDocument);
return this.usersService.findById(setUserJob.userId);
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
@ApiBearerAuth('JWT')
@ApiOperation({ description: 'Set user employer' })
@ApiResponse({ status: HttpStatus.OK, description: 'Return user profile' })
@ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'User does not exist' })
@ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'Employer does not exist' })
@Put('setUserEmployer')
public async setUserEmployer(@Body() setUserEmployer: SetUserEmployerDto): Promise<IUser> {
this.logger.debug(`setUserEmployer`);
const employerDocument = await this.employerService.findOne(setUserEmployer.employerId);
if (!employerDocument) {
this.logger.warn(`Employer does not exist: ${setUserEmployer.employerId}`);
throw new HttpException('Employer does not exist', HttpStatus.BAD_REQUEST);
}
const userDocument = await this.usersService.findById(setUserEmployer.userId);
if (!userDocument) {
this.logger.warn(`User does not exist: ${setUserEmployer.userId}`);
throw new HttpException('User does not exist', HttpStatus.BAD_REQUEST);
}
await this.usersService.updateUserEmployer(userDocument._id, employerDocument);
return this.usersService.findById(setUserEmployer.userId);
}
}
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty } from 'class-validator';
export class MergeEmployerDto {
@IsNotEmpty()
@ApiProperty({ type: String })
sourceEmployerId: string;
@IsNotEmpty()
@ApiProperty({ type: String })
targetEmployerId: string;
}