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 (4)
Showing
with 861 additions and 58 deletions
......@@ -2340,7 +2340,7 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true
},
"proxy-middleware": {
......@@ -3292,6 +3292,84 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"@mailchimp/mailchimp_marketing": {
"version": "3.0.78",
"resolved": "https://registry.npmjs.org/@mailchimp/mailchimp_marketing/-/mailchimp_marketing-3.0.78.tgz",
"integrity": "sha512-LAerA09fQ7opelydPolYez12mZ+TLQ+zDvHzweeAk9S+yI1bqBpuOvJVbe+3G0fsOqSbDTEUUBwUlncdAmShRA==",
"requires": {
"dotenv": "^8.2.0",
"superagent": "3.8.1"
},
"dependencies": {
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"requires": {
"ms": "^2.1.1"
}
},
"form-data": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
"integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"superagent": {
"version": "3.8.1",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.1.tgz",
"integrity": "sha512-VMBFLYgFuRdfeNQSMLbxGSLfmXL/xc+OO+BZp41Za/NRDBet/BNbkRJrYzCUu0u4GU0i/ml2dtT8b9qgkw9z6Q==",
"requires": {
"component-emitter": "^1.2.0",
"cookiejar": "^2.1.0",
"debug": "^3.1.0",
"extend": "^3.0.0",
"form-data": "^2.3.1",
"formidable": "^1.1.1",
"methods": "^1.1.1",
"mime": "^1.4.1",
"qs": "^6.5.1",
"readable-stream": "^2.0.5"
}
}
}
},
"@mapbox/node-pre-gyp": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.8.tgz",
......@@ -5046,7 +5124,7 @@
"append-field": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
"integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY="
},
"aproba": {
"version": "1.2.0",
......@@ -5123,7 +5201,7 @@
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"array-from": {
"version": "2.1.1",
......@@ -6232,8 +6310,7 @@
"component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
"dev": true
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
},
"concat-map": {
"version": "0.0.1",
......@@ -6821,13 +6898,12 @@
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"cookiejar": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
"integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==",
"dev": true
"integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
},
"copy-descriptor": {
"version": "0.1.1",
......@@ -8282,6 +8358,11 @@
}
}
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extend-shallow": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
......@@ -8713,8 +8794,7 @@
"formidable": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
"integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==",
"dev": true
"integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q=="
},
"forwarded": {
"version": "0.2.0",
......@@ -12101,7 +12181,7 @@
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"memfs": {
"version": "3.4.7",
......@@ -12233,7 +12313,7 @@
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"merge-source-map": {
"version": "1.0.4",
......@@ -12747,17 +12827,17 @@
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
......@@ -13204,7 +13284,7 @@
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"p-cancelable": {
......@@ -13392,7 +13472,7 @@
"pause": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
"integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
"integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10="
},
"pause-stream": {
"version": "0.0.11",
......@@ -13773,7 +13853,7 @@
"rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"dev": true,
"requires": {
"resolve": "^1.1.6"
......@@ -16201,7 +16281,7 @@
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"w3c-hr-time": {
"version": "1.0.2",
......@@ -16571,7 +16651,7 @@
"xml": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
"integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==",
"integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=",
"dev": true
},
"xml-name-validator": {
......
......@@ -17,7 +17,7 @@
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"release": "standard-version",
"init-db": "node ./scripts/init-db.js",
"test": "jest",
"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",
......@@ -28,6 +28,7 @@
},
"dependencies": {
"@elastic/elasticsearch": "^7.12.0",
"@mailchimp/mailchimp_marketing": "^3.0.78",
"@nestjs/axios": "^0.1.0",
"@nestjs/common": "^9.0.11",
"@nestjs/config": "^0.6.3",
......
// 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,
},
],
};
......@@ -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);
});
});
......@@ -6,6 +6,7 @@ import { AuthServiceMock } from '../../test/mock/services/auth.mock.service';
import { ConfigurationModule } from '../configuration/configuration.module';
import { MailerModule } from '../mailer/mailer.module';
import { User } from '../users/schemas/user.schema';
import { UserRegistrySearchService } from '../users/services/userRegistry-search.service';
import { UsersService } from '../users/services/users.service';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
......@@ -29,6 +30,10 @@ describe('AuthController', () => {
providers: [
AuthService,
UsersService,
{
provide: UserRegistrySearchService,
useClass: jest.fn(),
},
{
provide: AuthService,
useClass: AuthServiceMock,
......
export interface IMailchimpSubscription {
id: string;
email_address: string;
status: string;
}
......@@ -2,4 +2,5 @@ import { Document } from 'mongoose';
export interface INewsletterSubscription extends Document {
email: string;
mailchimpId: string;
}
......@@ -7,6 +7,9 @@ export type NewsletterSubscriptionDocument = NewsletterSubscription & Document;
export class NewsletterSubscription {
@Prop({ required: true })
email: string;
@Prop({ required: true })
mailchimpId: string;
}
export const NewsletterSubscriptionSchema = SchemaFactory.createForClass(NewsletterSubscription);
......@@ -29,16 +29,20 @@ describe('NewsletterController', () => {
});
it('should subscribe user', async () => {
const result = { email: 'email@test.com' };
jest.spyOn(controller, 'newsletterSubscribe').mockImplementation(async (): Promise<{ email }> => result);
const email = { email: 'email@test.com' };
const result = { email: 'email@test.com', mailchimpId: 'test' };
jest
.spyOn(controller, 'newsletterSubscribe')
.mockImplementation(async (): Promise<{ email; mailchimpId }> => result);
const email = { email: 'email@test.com', mailchimpId: 'test' };
expect(await controller.newsletterSubscribe(email)).toBe(result);
});
it('should unsubscribe user', async () => {
const result = { email: 'email@test.com' };
jest.spyOn(controller, 'newsletterUnsubscribe').mockImplementation(async (): Promise<{ email }> => result);
const email = { email: 'email@test.com' };
const result = { email: 'email@test.com', mailchimpId: 'test' };
jest
.spyOn(controller, 'newsletterUnsubscribe')
.mockImplementation(async (): Promise<{ email; mailchimpId }> => result);
const email = { email: 'email@test.com', mailchimpId: 'test' };
expect(await controller.newsletterUnsubscribe(email)).toBe(result);
});
});
......@@ -5,7 +5,11 @@ import { Test, TestingModule } from '@nestjs/testing';
import { INewsletterSubscription } from './interface/newsletter-subscription.interface';
import { NewsletterSubscription } from './newsletter-subscription.schema';
import { NewsletterService } from './newsletter.service';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mailchimp = require('@mailchimp/mailchimp_marketing');
jest.mock('@mailchimp/mailchimp_marketing');
describe('NewsletterService', () => {
const OLD_ENV = process.env;
let service: NewsletterService;
const mockNewsletterModel = {
......@@ -18,6 +22,7 @@ describe('NewsletterService', () => {
};
beforeEach(async () => {
jest.resetModules(); // Most important - it clears the cache
const module: TestingModule = await Test.createTestingModule({
imports: [HttpModule],
providers: [
......@@ -30,6 +35,15 @@ describe('NewsletterService', () => {
}).compile();
service = module.get<NewsletterService>(NewsletterService);
process.env = { ...OLD_ENV }; // Make a copy
process.env.MC_LIST_ID = 'abcde';
process.env.MC_API_KEY = 'k3y';
process.env.MC_SERVER = 's3rv3r';
});
afterAll(() => {
process.env = OLD_ENV; // Restore old environment
});
it('should be defined', () => {
......@@ -54,6 +68,7 @@ describe('NewsletterService', () => {
it('it should add a subscription for email test2@test.com', async () => {
const result: INewsletterSubscription = { email: 'test2@test.com' } as INewsletterSubscription;
const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' };
mailchimp.lists.addListMember.mockResolvedValueOnce({ email_address: 'test2@test.com' });
jest
.spyOn(service, 'findOne')
.mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => undefined)
......@@ -63,6 +78,42 @@ describe('NewsletterService', () => {
const subscription = await service.newsletterSubscribe('test2@test.com');
expect(subscription).toEqual({ email: 'test2@test.com' });
});
it('it should return mailchimp 400 issue', async () => {
const result: INewsletterSubscription = { email: 'test2@test.com' } as INewsletterSubscription;
const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' };
mailchimp.lists.addListMember.mockRejectedValueOnce({ status: 400 });
jest
.spyOn(service, 'findOne')
.mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => undefined)
.mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result);
mockNewsletterModel.create.mockResolvedValueOnce(_doc);
try {
await service.newsletterSubscribe('test2@test.com');
expect(true).toBe(false);
} catch (e) {
expect(e.message).toBe('Email already exists');
expect(e.status).toEqual(HttpStatus.BAD_REQUEST);
}
});
it('it should return mailchimp 500 issue', async () => {
const result: INewsletterSubscription = { email: 'test2@test.com' } as INewsletterSubscription;
const _doc = { _id: 'a1aaaaa1a1', email: 'test2@test.com' };
mailchimp.lists.addListMember.mockRejectedValueOnce({ status: 500 });
jest
.spyOn(service, 'findOne')
.mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => undefined)
.mockImplementationOnce(async (): Promise<INewsletterSubscription | undefined> => result);
mockNewsletterModel.create.mockResolvedValueOnce(_doc);
try {
await service.newsletterSubscribe('test2@test.com');
expect(true).toBe(false);
} catch (e) {
expect(e.message).toBe('Server error');
expect(e.status).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
}
});
});
describe('newsletterUnsubscribe', () => {
it('it should not remove subscription for email test@test.com : does not exist', async () => {
......@@ -135,4 +186,23 @@ describe('NewsletterService', () => {
expect(findOneEmail.length).toBe(2);
});
});
describe('updateNewsletterSubscription', () => {
it('should update existing user subscription', () => {
mailchimp.lists.getListMembersInfo.mockResolvedValueOnce({ total_items: 10 }).mockResolvedValueOnce({
members: [
{ email_address: 'a@a.com', status: 'subscribed' },
{ email_address: 'test@test.com', status: 'unsubscribed' },
{ email_address: 'test2@test.com', status: 'unsubscribed' },
],
});
const result = { email: 'test2@test.com' } as INewsletterSubscription;
const spyer = jest.spyOn(mockNewsletterModel, 'findOne');
// jest.spyOn(service, 'findOne').mockResolvedValueOnce(result).mockResolvedValueOnce(result);
mockNewsletterModel.findOne.mockResolvedValueOnce(result).mockResolvedValueOnce(null);
service.updateNewsletterSubscription();
expect(spyer).toBeCalledTimes(2);
// expect(spyerDelete).toBeCalledTimes(1);
});
});
});
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Cron, CronExpression } from '@nestjs/schedule';
import { Model } from 'mongoose';
import { IMailchimpSubscription } from './interface/mailchimp-subscription';
import { INewsletterSubscription } from './interface/newsletter-subscription.interface';
import { NewsletterSubscription, NewsletterSubscriptionDocument } from './newsletter-subscription.schema';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mailchimp = require('@mailchimp/mailchimp_marketing');
@Injectable()
export class NewsletterService {
private readonly logger = new Logger(NewsletterService.name);
private LIST_ID = process.env.MC_LIST_ID;
constructor(
@InjectModel(NewsletterSubscription.name) private newsletterSubscriptionModel: Model<INewsletterSubscription>
) {}
) {
// Configure mailchimp client
mailchimp.setConfig({
apiKey: process.env.MC_API_KEY,
server: process.env.MC_SERVER,
});
}
@Cron(CronExpression.EVERY_DAY_AT_3AM)
public async updateNewsletterSubscription(): Promise<void> {
this.logger.debug('updateNewsletterSubscription');
const { total_items } = await mailchimp.lists.getListMembersInfo(this.LIST_ID);
const { members } = await mailchimp.lists.getListMembersInfo(this.LIST_ID, {
fields: ['members.email_address,members.id,members.status'],
count: total_items,
});
const memberToRemove = members.filter((user: IMailchimpSubscription) => user.status !== 'subscribed');
memberToRemove.forEach(async (member: IMailchimpSubscription) => {
const userSubscription = await this.findOne(member.email_address);
if (userSubscription) {
this.logger.log(`Remove subscription ${member.id}`);
userSubscription.deleteOne();
}
});
}
public async newsletterSubscribe(email: string): Promise<NewsletterSubscription> {
this.logger.debug('newsletterSubscribe');
const existingEmail = await this.findOne(email);
if (existingEmail) {
throw new HttpException('Email already exists', HttpStatus.BAD_REQUEST);
}
await this.newsletterSubscriptionModel.create({ email: email });
return this.findOne(email);
try {
const member = await mailchimp.lists.addListMember(this.LIST_ID, {
email_address: email,
status: 'subscribed',
});
await this.newsletterSubscriptionModel.create({ email: email, mailchimpId: member.id });
return this.findOne(email);
} catch (e) {
if (e.status === 400) {
this.logger.error(`Error ${e.status}, user might already exist in mailchimplist`);
throw new HttpException('Email already exists', HttpStatus.BAD_REQUEST);
} else {
this.logger.error(`Mailchimp configuration error`);
throw new HttpException('Server error', HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
public async newsletterUnsubscribe(email: string): Promise<NewsletterSubscription> {
this.logger.debug('newsletterUnsubscribe');
const subscription = await this.findOne(email);
if (!subscription) {
throw new HttpException('Invalid email', HttpStatus.BAD_REQUEST);
}
await mailchimp.lists.setListMember(this.LIST_ID, subscription.mailchimpId, {
email_address: email,
status: 'unsubscribed',
});
return subscription.deleteOne();
}
public async findOne(mail: string): Promise<INewsletterSubscription | undefined> {
this.logger.debug('findOne');
return this.newsletterSubscriptionModel.findOne({ email: mail });
}
public async searchNewsletterSubscription(searchString: string): Promise<NewsletterSubscriptionDocument[]> {
this.logger.debug('searchNewsletterSubscription');
return this.newsletterSubscriptionModel.find({ email: new RegExp(searchString, 'i') });
}
public async countNewsletterSubscriptions(): Promise<number> {
this.logger.debug('countNewsletterSubscriptions');
return this.newsletterSubscriptionModel.countDocuments({});
}
public async findAll(): Promise<NewsletterSubscription[]> {
this.logger.debug('findAll');
return this.newsletterSubscriptionModel.find();
}
}
import { HttpModule } from '@nestjs/axios';
import { HttpStatus } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import * as bcrypt from 'bcrypt';
import { Types } from 'mongoose';
import { personalOffersDataMock } from '../../../test/mock/data/personalOffers.mock.data';
import { structuresDocumentDataMock } from '../../../test/mock/data/structures.mock.data';
import { structureMockDto, structuresDocumentDataMock } from '../../../test/mock/data/structures.mock.data';
import { mockParametersModel } from '../../../test/mock/services/parameters.mock.service';
import { UsersServiceMock } from '../../../test/mock/services/user.mock.service';
import { CategoriesFormationsService } from '../../categories/services/categories-formations.service';
......@@ -36,6 +37,7 @@ describe('StructuresService', () => {
exec: jest.fn(),
find: jest.fn(),
populate: jest.fn(),
save: jest.fn(),
};
const structuresSearchServiceMock = {
......@@ -162,6 +164,9 @@ describe('StructuresService', () => {
personalOffers: [],
},
]),
dropIndex: jest.fn(),
createStructureIndex: jest.fn(),
indexStructure: jest.fn(),
};
const mockCategoriesFormationsService = {
......@@ -263,9 +268,14 @@ describe('StructuresService', () => {
expect(service).toBeDefined();
});
it('should Initiate structure', () => {
const res = service.initiateStructureIndex();
expect(res).toBeTruthy();
it('should Initiate structure index', async () => {
const spyerIndex = jest.spyOn(structuresSearchServiceMock, 'indexStructure');
const spyerDrop = jest.spyOn(structuresSearchServiceMock, 'dropIndex');
const spyerCreate = jest.spyOn(structuresSearchServiceMock, 'createStructureIndex');
await service.initiateStructureIndex();
expect(spyerCreate).toBeCalledTimes(1);
expect(spyerDrop).toBeCalledTimes(1);
expect(spyerIndex).toBeCalledTimes(1);
});
describe('should searchForStructures', () => {
......@@ -358,12 +368,25 @@ describe('StructuresService', () => {
});
});
it('should create structure', () => {
const structure = new StructureDto();
let res = service.create(null, structure);
expect(res).toBeTruthy();
res = service.create('tsfsf6296', structure);
expect(res).toBeTruthy();
describe('create', () => {
it('should return invalid profile', async () => {
const structure = structureMockDto;
try {
await service.create('test@test.com', structure);
expect(true).toBe(false);
} catch (e) {
expect(e.message).toEqual('Invalid profile');
expect(e.status).toEqual(HttpStatus.NOT_FOUND);
}
});
// it('should have valid profile and create structure', async () => {
// const structure = structureMockDto;
// const spyer = jest.spyOn(mockStructureModel, 'save');
// const spyerIndex = jest.spyOn(structuresSearchServiceMock, 'indexStructure');
// await service.create('pauline.dupont@mii.com', structure);
// expect(spyer).toBeCalledTimes(1); // Should create structure in DB
// expect(spyerIndex).toBeCalledTimes(1); // Should index structure
// });
});
it('should search structure', () => {
......
......@@ -107,8 +107,8 @@ export class StructuresService {
return structures.sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id));
}
public async create(idUser: string, structure: StructureDto): Promise<Structure> {
const user = await this.userService.findOne(idUser);
public async create(email: string, structure: StructureDto): Promise<Structure> {
const user = await this.userService.findOne(email);
if (!user) {
throw new HttpException('Invalid profile', HttpStatus.NOT_FOUND);
}
......
import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import { mulitpleUsers, mulitpleUsersES } from '../../../test/mock/data/users.mock.data';
import { mockJwtAuthGuard } from '../../../test/mock/guards/jwt-auth.mock.guard';
import { mockRoleGuard } from '../../../test/mock/guards/role.mock.guard';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { ConfigurationModule } from '../../configuration/configuration.module';
import { RolesGuard } from '../guards/roles.guard';
import { User } from '../schemas/user.schema';
import { UserRegistryService } from '../services/userRegistry.service';
import { UsersRegistryController } from './userRegistry.controller';
describe('UserRegistryController', () => {
let controller: UsersRegistryController;
const userRegistryServiceMock = {
findAllForIndexation: jest.fn(),
countAllUserRegistry: jest.fn(),
findAllUserRegistry: jest.fn(),
findUsersByNameEmployerOrJob: jest.fn(),
searchByNameAndSurname: jest.fn(),
initUserRegistryIndex: jest.fn(),
populateES: jest.fn(),
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [ConfigurationModule],
providers: [
{
provide: UserRegistryService,
useValue: userRegistryServiceMock,
},
{
provide: getModelToken('User'),
useValue: User,
},
],
controllers: [UsersRegistryController],
})
.overrideGuard(JwtAuthGuard)
.useValue(mockJwtAuthGuard)
.overrideGuard(RolesGuard)
.useValue(mockRoleGuard)
.compile();
controller = module.get<UsersRegistryController>(UsersRegistryController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
describe('findAll', () => {
it('should findAll with searchTerm, job and employer', async () => {
userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
const reply = await controller.findAll({ search: 'adm' }, { page: 1, job: ['CNFS'], employer: ['Pimms'] });
expect(reply).toStrictEqual([mulitpleUsers[0]]);
});
it('should findAll with searchTerm, empty job and empty employer', async () => {
userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
const reply = await controller.findAll({ search: 'adm' }, { page: 1, job: [], employer: [] });
expect(reply).toStrictEqual([mulitpleUsers[0]]);
});
it('should findAll with searchTerm and no filter arrays', async () => {
userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
const reply = await controller.findAll({ search: 'adm' }, { page: 1 });
expect(reply).toStrictEqual([mulitpleUsers[0]]);
});
it('should findAll with searchTerm and empty job', async () => {
userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
const reply = await controller.findAll({ search: 'adm' }, { page: 1, job: [] });
expect(reply).toStrictEqual([mulitpleUsers[0]]);
});
it('should findAll with searchTerm and empty employer', async () => {
userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
const reply = await controller.findAll({ search: 'adm' }, { page: 1, employer: [] });
expect(reply).toStrictEqual([mulitpleUsers[0]]);
});
it('should findAll with no searchTerm and employer filter', async () => {
userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
const reply = await controller.findAll({ search: '' }, { page: 1, employer: ['CAF'] });
expect(reply).toStrictEqual([mulitpleUsers[0]]);
});
it('should findAll with no searchTerm and job filter', async () => {
userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
const reply = await controller.findAll({ search: '' }, { page: 1, job: ['CNFS'] });
expect(reply).toStrictEqual([mulitpleUsers[0]]);
});
it('should findAll with no searchTerm and filters', async () => {
userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
const reply = await controller.findAll({ search: '' }, { page: 1, job: ['CNFS'], employer: ['CAF'] });
expect(reply).toStrictEqual([mulitpleUsers[0]]);
});
it('should findAll with searchTerm and undefined filters', async () => {
userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
const reply = await controller.findAll({ search: 'adm' });
expect(reply).toStrictEqual([mulitpleUsers[0]]);
});
it('should findAll with no searchTerm and no filter arrays', async () => {
userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(mulitpleUsers);
const reply = await controller.findAll({ search: '' }, { page: 1 });
expect(reply).toBe(mulitpleUsers);
});
it('should findAll with empty search end undefined filters', async () => {
userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(mulitpleUsers);
const reply = await controller.findAll({ search: '' });
expect(reply).toBe(mulitpleUsers);
});
});
describe('findAllCount', () => {
it('should findAllCount', async () => {
userRegistryServiceMock.countAllUserRegistry.mockResolvedValue(10);
const reply = await controller.findAllCount();
expect(reply).toStrictEqual(10);
});
});
describe('resetES', () => {
it('should reset elastic search indexes', async () => {
userRegistryServiceMock.initUserRegistryIndex.mockResolvedValue(mulitpleUsersES);
const reply = await controller.resetES();
expect(reply).toStrictEqual(mulitpleUsersES);
});
});
});
import { Body, Controller, Get, Logger, Post, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
import { Roles } from '../decorators/roles.decorator';
import { RolesGuard } from '../guards/roles.guard';
import { IUserRegistry, UserRegistryPaginatedResponse } from '../interfaces/userRegistry.interface';
import { UserRegistryService } from '../services/userRegistry.service';
@ApiTags('userRegistry')
@Controller('userRegistry')
export class UsersRegistryController {
private readonly logger = new Logger(UsersRegistryController.name);
constructor(private userRegistryService: UserRegistryService) {}
/**
* Find all users in Registry. If search is given as param, filter on it. Otherwise return everything. Results comes paginated (default is 20 per page, defined in service)
* @param query {Query}
* @returns {PaginatedResponse}
*/
@UseGuards(JwtAuthGuard)
@ApiBearerAuth('JWT')
@Post()
public async findAll(
@Query() query?: { search: string },
@Body() filters?: { job?: string[]; employer?: string[]; page: number }
): Promise<UserRegistryPaginatedResponse> {
if (query.search || filters?.job?.length || filters?.employer?.length) {
this.logger.debug(`findAll with query ${query.search}`);
return this.userRegistryService.findUsersByNameEmployerOrJob(
query.search || '',
filters?.page || 1,
filters?.job || [],
filters?.employer || []
);
}
this.logger.debug('findAll without query');
return this.userRegistryService.findAllUserRegistry(filters?.page || 1);
}
/**
* Return every user in registry
* @returns {Promise<number>}
*/
@Get('/count')
public async findAllCount(): Promise<number> {
this.logger.debug('findAll UserRegistry');
return this.userRegistryService.countAllUserRegistry();
}
/**
* Init or reset search index for users
* @returns {IUserRegistry[]}
*/
@Post('searchIndex')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin')
public async resetES(): Promise<IUserRegistry[]> {
return this.userRegistryService.initUserRegistryIndex();
}
}
import { Employer } from '../schemas/employer.schema';
import { Job } from '../schemas/job.schema';
export interface UserRegistrySearchBody {
id: string;
name: string;
surname: string;
job: Job;
employer: Employer;
}
import { UserRegistrySearchBody } from './userRegistry-search-body.interface';
export interface UserRegistrySearchResult {
hits: {
total: number;
max_score: number;
hits: Array<{
_score: number;
_source: UserRegistrySearchBody;
}>;
};
}
import { IUser } from './user.interface';
export type IUserRegistry = Omit<
IUser,
| 'email'
| 'phone'
| 'password'
| 'emailVerified'
| 'validationToken'
| 'resetPasswordToken'
| 'role'
| 'changeEmailToken'
| 'newEmail'
| 'structuresLink'
| 'pendingStructuresLink'
| 'structureOutdatedMailSent'
| 'personalOffers'
| 'description'
>;
export interface UserRegistryPaginatedResponse {
count: number;
docs: IUserRegistry[];
}