diff --git a/scripts/init-index.js b/scripts/init-index.js index e23d29fdf8bc24511b4f794a13d47a9219a3c2be..0ddd701395ae700a828aaefc51466f6c23bfbb85 100644 --- a/scripts/init-index.js +++ b/scripts/init-index.js @@ -29,6 +29,15 @@ axios 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'); + console.error(error); + }); }) .catch((error) => { console.error('Error in auth'); diff --git a/src/mailer/mail-templates/structureOutdatedInfo.json b/src/mailer/mail-templates/structureOutdatedInfo.json index 1782ea483e33fb07f29c92e7a12f758f23f2e395..924c0168c6746baf1c5918aa3ac78165009e79da 100644 --- a/src/mailer/mail-templates/structureOutdatedInfo.json +++ b/src/mailer/mail-templates/structureOutdatedInfo.json @@ -1,3 +1,3 @@ { - "subject": "Votre fiche structure n'est plus a jour, Réseau des Acteurs de la Médiation Numérique de la Métropole de Lyon" + "subject": "Votre fiche structure n'est plus à jour, Réseau des Acteurs de l'Inclusion Numérique de la Métropole de Lyon" } diff --git a/src/parameters/parameters.controller.ts b/src/parameters/parameters.controller.ts index fcd6e4883f3f06248445add283831a67b49b572f..7c26bc9504632603edb6f0e6031479e0b814c82e 100644 --- a/src/parameters/parameters.controller.ts +++ b/src/parameters/parameters.controller.ts @@ -12,8 +12,6 @@ export class ParametersController { constructor(private parametersService: ParametersService) {} @Get() - @UseGuards(JwtAuthGuard, RolesGuard) - @Roles('admin') public async getParameters(): Promise<Parameters> { return this.parametersService.getParameters(); } diff --git a/src/shared/utils.ts b/src/shared/utils.ts index 0bca461a48a19ee86e63a7ddf490d0555a4b1ed2..8216e4edc56d39c19a3efd1311cce4b5be942416 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -21,3 +21,33 @@ export function rewriteGhostImgUrl(configService: ConfigurationService, itemData export function hasAdminRole(user: User): boolean { return user.role === UserRole.admin; } + +export const es_settings_homemade_french = { + analysis: { + filter: { + french_elision: { + type: 'elision', + articles_case: true, + articles: ['l', 'm', 't', 'qu', 'n', 's', 'j', 'd', 'c', 'jusqu', 'quoiqu', 'lorsqu', 'puisqu'], + }, + french_stop: { + type: 'stop', + stopwords: '_french_', + }, + french_stemmer: { + type: 'stemmer', + language: 'minimal_french', + }, + }, + analyzer: { + homemade_french: { + tokenizer: 'standard', + filter: ['lowercase', 'asciifolding', 'french_elision', 'french_stop', 'french_stemmer'], + }, + homemade_french_stopless: { + tokenizer: 'standard', + filter: ['lowercase', 'asciifolding', 'french_elision', 'french_stemmer'], + }, + }, + }, +}; diff --git a/src/structures/services/structures-search.service.ts b/src/structures/services/structures-search.service.ts index 6356387af587430804cef421e383eb51af1679cf..5403625f6ab0269d02dcab234fa77f5af7606aa4 100644 --- a/src/structures/services/structures-search.service.ts +++ b/src/structures/services/structures-search.service.ts @@ -3,6 +3,7 @@ import { ElasticsearchService } from '@nestjs/elasticsearch'; import { Structure, StructureDocument } from '../schemas/structure.schema'; import { StructureSearchBody } from '../interfaces/structure-search-body.interface'; import { StructureSearchResult } from '../interfaces/structure-search-response.interface'; +import { es_settings_homemade_french } from '../../shared/utils'; @Injectable() export class StructuresSearchService { @@ -55,35 +56,7 @@ export class StructuresSearchService { }, }, }, - settings: { - analysis: { - filter: { - french_elision: { - type: 'elision', - articles_case: true, - articles: ['l', 'm', 't', 'qu', 'n', 's', 'j', 'd', 'c', 'jusqu', 'quoiqu', 'lorsqu', 'puisqu'], - }, - french_stop: { - type: 'stop', - stopwords: '_french_', - }, - french_stemmer: { - type: 'stemmer', - language: 'minimal_french', - }, - }, - analyzer: { - homemade_french: { - tokenizer: 'standard', - filter: ['lowercase', 'asciifolding', 'french_elision', 'french_stop', 'french_stemmer'], - }, - homemade_french_stopless: { - tokenizer: 'standard', - filter: ['lowercase', 'asciifolding', 'french_elision', 'french_stemmer'], - }, - }, - }, - }, + settings: es_settings_homemade_french, }, }); } diff --git a/src/users/controllers/userRegistry.controller.spec.ts b/src/users/controllers/userRegistry.controller.spec.ts index 1cbfb3d63e9e376ac30804a647a558b406dcd001..6073bcd1d0c272893f6dc0746d9132bd36f4f5ef 100644 --- a/src/users/controllers/userRegistry.controller.spec.ts +++ b/src/users/controllers/userRegistry.controller.spec.ts @@ -1,6 +1,6 @@ import { getModelToken } from '@nestjs/mongoose'; import { Test, TestingModule } from '@nestjs/testing'; -import { mulitpleUsers, mulitpleUsersES } from '../../../test/mock/data/users.mock.data'; +import { multipleUsers } 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'; @@ -53,59 +53,59 @@ describe('UserRegistryController', () => { describe('findAll', () => { it('should findAll with searchTerm, job and employer', async () => { - userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]); + userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([multipleUsers[0]]); const reply = await controller.findAll({ search: 'adm' }, { page: 1, job: ['CNFS'], employer: ['Pimms'] }); - expect(reply).toStrictEqual([mulitpleUsers[0]]); + expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with searchTerm, empty job and empty employer', async () => { - userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]); + userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([multipleUsers[0]]); const reply = await controller.findAll({ search: 'adm' }, { page: 1, job: [], employer: [] }); - expect(reply).toStrictEqual([mulitpleUsers[0]]); + expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with searchTerm and no filter arrays', async () => { - userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]); + userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([multipleUsers[0]]); const reply = await controller.findAll({ search: 'adm' }, { page: 1 }); - expect(reply).toStrictEqual([mulitpleUsers[0]]); + expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with searchTerm and empty job', async () => { - userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]); + userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([multipleUsers[0]]); const reply = await controller.findAll({ search: 'adm' }, { page: 1, job: [] }); - expect(reply).toStrictEqual([mulitpleUsers[0]]); + expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with searchTerm and empty employer', async () => { - userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]); + userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([multipleUsers[0]]); const reply = await controller.findAll({ search: 'adm' }, { page: 1, employer: [] }); - expect(reply).toStrictEqual([mulitpleUsers[0]]); + expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with no searchTerm and employer filter', async () => { - userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]); + userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([multipleUsers[0]]); const reply = await controller.findAll({ search: '' }, { page: 1, employer: ['CAF'] }); - expect(reply).toStrictEqual([mulitpleUsers[0]]); + expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with no searchTerm and job filter', async () => { - userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]); + userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([multipleUsers[0]]); const reply = await controller.findAll({ search: '' }, { page: 1, job: ['CNFS'] }); - expect(reply).toStrictEqual([mulitpleUsers[0]]); + expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with no searchTerm and filters', async () => { - userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]); + userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([multipleUsers[0]]); const reply = await controller.findAll({ search: '' }, { page: 1, job: ['CNFS'], employer: ['CAF'] }); - expect(reply).toStrictEqual([mulitpleUsers[0]]); + expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with searchTerm and undefined filters', async () => { - userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]); + userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([multipleUsers[0]]); const reply = await controller.findAll({ search: 'adm' }); - expect(reply).toStrictEqual([mulitpleUsers[0]]); + expect(reply).toStrictEqual([multipleUsers[0]]); }); it('should findAll with no searchTerm and no filter arrays', async () => { - userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(mulitpleUsers); + userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(multipleUsers); const reply = await controller.findAll({ search: '' }, { page: 1 }); - expect(reply).toBe(mulitpleUsers); + expect(reply).toBe(multipleUsers); }); it('should findAll with empty search end undefined filters', async () => { - userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(mulitpleUsers); + userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(multipleUsers); const reply = await controller.findAll({ search: '' }); - expect(reply).toBe(mulitpleUsers); + expect(reply).toBe(multipleUsers); }); }); describe('findAllCount', () => { @@ -117,9 +117,9 @@ describe('UserRegistryController', () => { }); describe('resetES', () => { it('should reset elastic search indexes', async () => { - userRegistryServiceMock.initUserRegistryIndex.mockResolvedValue(mulitpleUsersES); + userRegistryServiceMock.initUserRegistryIndex.mockResolvedValue(multipleUsers); const reply = await controller.resetES(); - expect(reply).toStrictEqual(mulitpleUsersES); + expect(reply).toStrictEqual(multipleUsers); }); }); }); diff --git a/src/users/services/employer-search.service.ts b/src/users/services/employer-search.service.ts index f39e479d01eb63a00cec7d7d6de5e0e50ad98dda..5a66dcec7143915128b376012bd703f1c3346dcb 100644 --- a/src/users/services/employer-search.service.ts +++ b/src/users/services/employer-search.service.ts @@ -1,5 +1,6 @@ import { Injectable, Logger } from '@nestjs/common'; import { ElasticsearchService } from '@nestjs/elasticsearch'; +import { es_settings_homemade_french } from '../../shared/utils'; import { EmployerSearchBody } from '../interfaces/employer-search-body.interface'; import { EmployerSearchResult } from '../interfaces/employer-search-response.interface'; import { Employer, EmployerDocument } from '../schemas/employer.schema'; @@ -29,18 +30,21 @@ export class EmployerSearchService { return this.elasticsearchService.indices.create({ index: this.index, body: { - settings: { - analysis: { - analyzer: { - default: { - type: 'french', - }, - default_search: { - type: 'french', + mappings: { + dynamic_templates: [ + { + strings: { + match_mapping_type: 'string', + mapping: { + type: 'text', + analyzer: 'homemade_french', + search_analyzer: 'homemade_french_stopless', + }, }, }, - }, + ], }, + settings: es_settings_homemade_french, }, }); } diff --git a/src/users/services/userRegistry-search.service.spec.ts b/src/users/services/userRegistry-search.service.spec.ts index b790a65f28ef5530ef6ddc35d6f81dd21d3de7c0..b6e995fd20cb6016545ea83dcdf4ef508104bdc3 100644 --- a/src/users/services/userRegistry-search.service.spec.ts +++ b/src/users/services/userRegistry-search.service.spec.ts @@ -1,5 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { mulitpleUsers, mulitpleUsersES } from '../../../test/mock/data/users.mock.data'; +import { multipleUsers } from '../../../test/mock/data/users.mock.data'; import { ConfigurationModule } from '../../configuration/configuration.module'; import { SearchModule } from '../../search/search.module'; import { IUserRegistry } from '../interfaces/userRegistry.interface'; @@ -19,7 +19,7 @@ describe('UserRegistrySearchService Search cases', () => { // Init test cases await service.dropIndex(); await service.createUserRegistryIndex(); - await Promise.all(mulitpleUsersES.map((user: any) => service.indexUserRegistry(user))); + await Promise.all(multipleUsers.map((user: any) => service.indexUserRegistry(user))); // wait for the new structures to be indexed before search await service.refreshIndexUserRegistry(); @@ -47,12 +47,12 @@ describe('UserRegistrySearchService Search cases', () => { }); describe('Indexation methods', () => { it('should index User', async () => { - const res = await Promise.all(mulitpleUsersES.map((user: any) => service.indexUserRegistry(user))); + const res = await Promise.all(multipleUsers.map((user: any) => service.indexUserRegistry(user))); expect(res).toBeTruthy(); expect(res.length).toBe(6); }); it('should update index', async () => { - const res = await service.update(mulitpleUsers[0] as IUserRegistry); + const res = await service.update(multipleUsers[0] as IUserRegistry); expect(res).toBeTruthy(); }); it('should delete index', async () => { diff --git a/src/users/services/userRegistry-search.service.ts b/src/users/services/userRegistry-search.service.ts index 43dd4cb63808bd31481bb131fb76911f81f0178a..829c98d1d3dee3104913a7e183c912d3cade06bc 100644 --- a/src/users/services/userRegistry-search.service.ts +++ b/src/users/services/userRegistry-search.service.ts @@ -1,5 +1,6 @@ import { Injectable, Logger } from '@nestjs/common'; import { ElasticsearchService } from '@nestjs/elasticsearch'; +import { es_settings_homemade_french } from '../../shared/utils'; import { UserRegistrySearchBody } from '../interfaces/userRegistry-search-body.interface'; import { UserRegistrySearchResult } from '../interfaces/userRegistry-search-response.interface'; import { IUserRegistry } from '../interfaces/userRegistry.interface'; @@ -15,10 +16,10 @@ export class UserRegistrySearchService { this.logger.debug(`indexUser ${user.name} ${user.surname}`); this.elasticsearchService.index<UserRegistrySearchResult, UserRegistrySearchBody>({ index: this.index, - id: user.id, + id: user._id, body: { name: user.name, - id: user.id, + id: user._id, surname: user.surname, job: user.job, employer: user.employer, @@ -32,18 +33,21 @@ export class UserRegistrySearchService { return this.elasticsearchService.indices.create({ index: this.index, body: { - settings: { - analysis: { - analyzer: { - default: { - type: 'french', - }, - default_search: { - type: 'french', + mappings: { + dynamic_templates: [ + { + strings: { + match_mapping_type: 'string', + mapping: { + type: 'text', + analyzer: 'homemade_french', + search_analyzer: 'homemade_french_stopless', + }, }, }, - }, + ], }, + settings: es_settings_homemade_french, }, }); } @@ -80,7 +84,7 @@ export class UserRegistrySearchService { public async search(searchString: string): Promise<any[]> { this.logger.debug(`search user with query: ${searchString}`); - searchString = searchString ? '*' + searchString + '*' : '*'; + searchString = searchString ? searchString + '*' : '*'; const { body } = await this.elasticsearchService.search<UserRegistrySearchResult>({ index: this.index, body: { @@ -97,7 +101,7 @@ export class UserRegistrySearchService { }, }); const sortedHits = body.hits.hits.filter(function (elem) { - return elem._score >= body.hits.max_score; + return elem._score >= body.hits.max_score / 1.5; }); return sortedHits.map((item) => item._source); } diff --git a/src/users/services/userRegistry.service.spec.ts b/src/users/services/userRegistry.service.spec.ts index 87eafc904a07506cf9d1b86cadf1de3bd345e086..a096276e1922fcecb73f955885d73301849db2b2 100644 --- a/src/users/services/userRegistry.service.spec.ts +++ b/src/users/services/userRegistry.service.spec.ts @@ -2,7 +2,7 @@ import { HttpModule } from '@nestjs/axios'; import { getModelToken } from '@nestjs/mongoose'; import { Test, TestingModule } from '@nestjs/testing'; import { Types } from 'mongoose'; -import { mulitpleUsers, mulitpleUsersES } from '../../../test/mock/data/users.mock.data'; +import { multipleUsers } from '../../../test/mock/data/users.mock.data'; import { ConfigurationModule } from '../../configuration/configuration.module'; import { IUserRegistry } from '../interfaces/userRegistry.interface'; import { EmployerService } from './employer.service'; @@ -141,16 +141,18 @@ describe('userRegistryService', () => { ], }; it('should findUsersByNameEmployerOrJob with string param and get a result', async () => { + mockUserRegistryModel.exec.mockResolvedValueOnce(result); mockUserRegistrySearchService.search.mockResolvedValueOnce(result); expect(await service.findUsersByNameEmployerOrJob('adm', 1)).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJob with string param and get no result', async () => { const emptyRes = { count: 0, docs: [] }; + mockUserRegistryModel.exec.mockResolvedValueOnce([]); mockUserRegistrySearchService.search.mockResolvedValueOnce([]); expect(await service.findUsersByNameEmployerOrJob('azerty', 1)).toStrictEqual(emptyRes); }); it('should findUsersByNameEmployerOrJob with no string param and filters', async () => { - const res = { count: 1, docs: [mulitpleUsersES[1]] }; + const res = { count: 1, docs: [multipleUsers[1]] }; const jobList = [ { hasPersonalOffer: true, @@ -159,15 +161,15 @@ describe('userRegistryService', () => { }, ]; const employerList = [{ name: 'Métropole', validated: true }]; - mockUserRegistrySearchService.search.mockResolvedValueOnce(mulitpleUsersES); + mockUserRegistrySearchService.search.mockResolvedValueOnce(multipleUsers); mockJobsService.findByName.mockResolvedValueOnce(jobList[0]); mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]); - mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers); + mockUserRegistryModel.exec.mockResolvedValueOnce(multipleUsers); expect(await service.findUsersByNameEmployerOrJob('', 1, ['CNFS'], ['Métropole'])).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJob with string param and filters', async () => { - const res = { count: 1, docs: [mulitpleUsersES[1]] }; + const res = { count: 1, docs: [multipleUsers[1]] }; const jobList = [ { hasPersonalOffer: true, @@ -176,10 +178,10 @@ describe('userRegistryService', () => { }, ]; const employerList = [{ name: 'Métropole', validated: true }]; - mockUserRegistrySearchService.search.mockResolvedValueOnce([mulitpleUsersES[1]]); + mockUserRegistrySearchService.search.mockResolvedValueOnce([multipleUsers[1]]); mockJobsService.findByName.mockResolvedValueOnce(jobList[0]); mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]); - mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers); + mockUserRegistryModel.exec.mockResolvedValueOnce(multipleUsers); expect(await service.findUsersByNameEmployerOrJob('Guil', 1, ['CNFS'], ['Métropole'])).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJob with string param and filters and return empty', async () => { @@ -199,16 +201,16 @@ describe('userRegistryService', () => { expect(await service.findUsersByNameEmployerOrJob('azerrttt', 1, ['CNFS'], ['Métropole'])).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJob with string param and one filter', async () => { - const res = { count: 2, docs: [mulitpleUsersES[0], mulitpleUsersES[2]] }; + const res = { count: 2, docs: [multipleUsers[0], multipleUsers[2]] }; const employerList = [{ name: 'CAF', validated: true }]; - mockUserRegistrySearchService.search.mockResolvedValueOnce(mulitpleUsersES); + mockUserRegistrySearchService.search.mockResolvedValueOnce(multipleUsers); mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]); - mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers); + mockUserRegistryModel.exec.mockResolvedValueOnce(multipleUsers); expect(await service.findUsersByNameEmployerOrJob('a', 1, [], ['CAF'])).toStrictEqual(res); }); it('should findUsersByNameEmployerOrJob with no string param and one employer filter', async () => { - const res = { count: 2, docs: [mulitpleUsersES[2], mulitpleUsersES[3]] }; + const res = { count: 2, docs: [multipleUsers[2], multipleUsers[3]] }; const jobList = [ { @@ -217,27 +219,27 @@ describe('userRegistryService', () => { validated: true, }, ]; - mockUserRegistrySearchService.search.mockResolvedValueOnce(mulitpleUsersES); + mockUserRegistrySearchService.search.mockResolvedValueOnce(multipleUsers); mockJobsService.findByName.mockResolvedValueOnce(jobList[0]); - mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers); + mockUserRegistryModel.exec.mockResolvedValueOnce(multipleUsers); expect(await service.findUsersByNameEmployerOrJob('', 1, ['Conseiller'], [])).toStrictEqual(res); }); }); describe('Search', () => { it('should initUserRegistryIndex', async () => { - mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers); + mockUserRegistryModel.exec.mockResolvedValueOnce(multipleUsers); mockUserRegistrySearchService.dropIndex.mockResolvedValueOnce({}); mockUserRegistrySearchService.createUserRegistryIndex.mockResolvedValueOnce({}); mockUserRegistrySearchService.indexUserRegistry.mockResolvedValueOnce({}); - expect(await service.initUserRegistryIndex()).toBe(mulitpleUsers); + expect(await service.initUserRegistryIndex()).toBe(multipleUsers); }); it('should findAllUserRegistry with page number 1', async () => { - mockUserRegistrySearchService.search.mockResolvedValueOnce([mulitpleUsers[0]]); + mockUserRegistrySearchService.search.mockResolvedValueOnce([multipleUsers[0]]); - expect(await service.searchByNameAndSurname('adm')).toStrictEqual([mulitpleUsers[0]]); + expect(await service.searchByNameAndSurname('adm')).toStrictEqual([multipleUsers[0]]); }); }); }); diff --git a/src/users/services/userRegistry.service.ts b/src/users/services/userRegistry.service.ts index 8f94a12a042a24c1baf0994d6dcf0428b6af229e..4f1156711516b534e44df1286ec08c39914bd1e5 100644 --- a/src/users/services/userRegistry.service.ts +++ b/src/users/services/userRegistry.service.ts @@ -65,7 +65,7 @@ export class UserRegistryService { const jobNames: string[] = jobList.map((job) => job.name); const employersNames: string[] = employersList.map((e) => e.name); // For each filter list (job or employer), we'll filter the main user list in order to get only the user that have a job or employer contained in the filters array - // For this, we une findexIndex method on job/employer name + // For this, we use findIndex method on job/employer name if (employersList?.length && jobList?.length) { return users.filter( @@ -80,6 +80,7 @@ export class UserRegistryService { if (jobList?.length) { return users.filter((user) => jobNames.findIndex((n) => user.job?.name === n) > -1); } + return users; } public async findUsersByNameEmployerOrJob( @@ -89,45 +90,34 @@ export class UserRegistryService { employers?: string[] ): Promise<UserRegistryPaginatedResponse> { const results = await this.userRegistrySearchService.search(searchParam); + const ids = results.map((result) => result.id); const limit = page * this.maxPerPage || this.maxPerPage; - if (jobs?.length || employers?.length) { - const jobList: Job[] = []; - const employersList: Employer[] = []; - if (jobs) { - for (const job of jobs) { - jobList.push(await this.jobsService.findByName(job)); - } + const jobList: Job[] = []; + const employersList: Employer[] = []; + if (jobs) { + for (const job of jobs) { + jobList.push(await this.jobsService.findByName(job)); } - if (employers) { - for (const employer of employers) { - employersList.push(await this.employerService.findByName(employer)); - } + } + if (employers) { + for (const employer of employers) { + employersList.push(await this.employerService.findByName(employer)); } - const resultsWithFilter = await this.userModel - .find({ - $or: [ - { - job: { $exists: true }, - }, - { - employer: { $exists: true }, - }, - ], - }) - .where('emailVerified') - .equals(true) - .select('name surname employer job _id ') - .populate('employer job') - .sort({ surname: 1 }) - .exec() - .then((res) => { - return this.callbackFilter(res, employersList, jobList); - }); - const idsWithFilter = resultsWithFilter.map((user) => user._id.toString()); - const mergedResults = results.filter((user) => idsWithFilter.includes(user.id.toString())); - return { count: mergedResults.length, docs: mergedResults.splice(0, limit) }; } - return { count: results.length, docs: results.splice(0, limit) }; + const resultsWithFilter = await this.userModel + .find({ + _id: { $in: ids }, + }) + .where('emailVerified') + .equals(true) + .select('name surname employer job _id ') + .populate('employer job') + .sort({ surname: 1 }) + .exec() + .then((res) => { + return this.callbackFilter(res, employersList, jobList); + }); + return { count: resultsWithFilter.length, docs: resultsWithFilter.splice(0, limit) }; } // SEARCH diff --git a/src/users/services/users.service.ts b/src/users/services/users.service.ts index 49fa79b8ad1a3839ff792f11519441a734c7f430..edfc5eda6f3f37b9801177a2114d8d3e77ad684b 100644 --- a/src/users/services/users.service.ts +++ b/src/users/services/users.service.ts @@ -286,6 +286,8 @@ export class UsersService { user.validationToken = null; user.emailVerified = true; user.save(); + const populatedResult = await this.findPopulatedUserRegistryById(userId); + this.userRegistrySearchService.update(populatedResult); return user; } else { throw new HttpException('Invalid token', HttpStatus.UNAUTHORIZED); diff --git a/test/mock/data/users.mock.data.ts b/test/mock/data/users.mock.data.ts index 01c362a058e9d204017d287f79e1d779d9c558dc..d59d47aa5b6edffbba9b223e7253e0328f065fb3 100644 --- a/test/mock/data/users.mock.data.ts +++ b/test/mock/data/users.mock.data.ts @@ -117,7 +117,7 @@ export const userDetails: IUser[] = [ }, ] as IUser[]; -export const mulitpleUsers: IUser[] = [ +export const multipleUsers: IUser[] = [ { _id: '627b85aea0466f0f132e1599', surname: 'ADMIN', @@ -209,97 +209,3 @@ export const mulitpleUsers: IUser[] = [ }, }, ] as IUser[]; - -//Elastic search doesn't support _id -export const mulitpleUsersES: IUser[] = [ - { - id: '627b85aea0466f0f132e1599', - surname: 'ADMIN', - name: 'Admin', - email: 'admin@admin.com', - employer: { - name: 'CAF', - validated: true, - }, - job: { - hasPersonalOffer: true, - name: 'CNFS', - validated: true, - }, - }, - { - id: '627b85aea0466f0f132e1598', - surname: 'Guilhem', - name: 'CARRON', - email: 'admin@admin.com', - employer: { - name: 'Métropole', - validated: true, - }, - job: { - hasPersonalOffer: true, - name: 'CNFS', - validated: true, - }, - }, - { - id: '627b85aea0466f0f132e1597', - surname: 'Jean-Paul', - name: 'DESCHAMPS', - email: 'admin@admin.com', - employer: { - name: 'CAF', - validated: true, - }, - job: { - hasPersonalOffer: true, - name: 'Conseiller', - validated: true, - }, - }, - { - id: '627b85aea0466f0f132e1596', - surname: 'Paula', - name: 'Dubois', - email: 'admin@admin.com', - employer: { - name: 'Pimms', - validated: true, - }, - job: { - hasPersonalOffer: true, - name: 'Conseiller', - validated: true, - }, - }, - { - id: '627b85aea0466f0f132e1595', - surname: 'Marine', - name: 'Ducal', - email: 'admin@admin.com', - employer: { - name: 'Médiateur', - validated: true, - }, - job: { - hasPersonalOffer: true, - name: 'CNFS', - validated: true, - }, - }, - { - id: '627b85aea0466f0f132e1594', - surname: 'Bastien', - name: 'Dumont', - email: 'admin@admin.com', - employer: { - name: 'Pimms', - validated: true, - }, - job: { - hasPersonalOffer: true, - name: 'CNFS', - validated: true, - }, - }, -] as IUser[];