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 (6)
......@@ -12,6 +12,10 @@ build:
image: docker:18.09
services:
- docker:18.09-dind
only:
- dev
- rec
- master
stage: build
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
......@@ -32,12 +36,15 @@ deploy_dev:
- docker system prune -a -f
code_analysis:
image: skilldlabs/sonar-scanner:3.4.0
image: skilldlabs/sonar-scanner:4.0.0
services:
- docker:18.09-dind
stage: sonar-analysis
only:
- dev
before_script:
- export NODE_PATH=$NODE_PATH:`npm root -g`
- npm install -g typescript
script:
- >
sonar-scanner
......@@ -48,3 +55,14 @@ code_analysis:
-Dsonar.host.url=${SONAR_URL}
-Dsonar.projectKey=${SONAR_PROJECT_KEY}
-Dsonar.login=${SONAR_TOKEN}
mr:
image: docker:18.09
services:
- docker:18.09-dind
stage: build
only:
- merge_requests
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build .
......@@ -3538,6 +3538,11 @@
"integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==",
"dev": true
},
"class-transformer": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.3.1.tgz",
"integrity": "sha512-cKFwohpJbuMovS8xVLmn8N2AUbAuc8pVo4zEfsUVo8qgECOogns1WVk/FkOZoxhOPTyTYFckuoH+13FO+MQ8GA=="
},
"class-utils": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
......
......@@ -30,6 +30,7 @@
"@nestjs/swagger": "^4.7.5",
"@types/bcrypt": "^3.0.0",
"bcrypt": "^5.0.0",
"class-transformer": "^0.3.1",
"class-validator": "^0.12.2",
"dotenv": "^8.2.0",
"ejs": "^3.1.5",
......
import { JwtModule, JwtService } from '@nestjs/jwt';
import { JwtModule } from '@nestjs/jwt';
import { getModelToken } from '@nestjs/mongoose';
import { PassportModule } from '@nestjs/passport';
import { Test, TestingModule } from '@nestjs/testing';
import { ConfigurationModule } from '../configuration/configuration.module';
import { MailerModule } from '../mailer/mailer.module';
import { User } from '../users/user.schema';
import { UsersModule } from '../users/users.module';
import { UsersService } from '../users/users.service';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { JwtStrategy } from './strategy/jwt.strategy';
describe('AuthController', () => {
let controller: AuthController;
......
......@@ -51,14 +51,14 @@ describe('AuthService', () => {
email: 'jacques.dupont@mii.com',
role: 0,
};
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' };
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'validateUser').mockImplementation(async (): Promise<any> => result);
expect(await service.validateUser(loginDto)).toBe(result);
});
it('should not validateUser', async () => {
const result = null;
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' };
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'validateUser').mockImplementation(async (): Promise<any> => result);
expect(await service.validateUser(loginDto)).toBe(result);
});
......@@ -67,28 +67,28 @@ describe('AuthService', () => {
describe('login', () => {
it('should login user jacques.dupont@mii.com', async () => {
const result = { username: ' jacques.dupont@mii.com', token: 'tok3n!1sfq' };
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' };
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'validateUser').mockImplementation(async (): Promise<{ username; token }> => result);
expect(await service.validateUser(loginDto)).toBe(result);
});
it('should not login jacques.dupont@mii.com, email not verified', async () => {
const result = new HttpException('Invalid credentials', HttpStatus.UNAUTHORIZED);
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' };
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'validateUser').mockImplementation(async (): Promise<any> => result);
expect(await service.validateUser(loginDto)).toBe(result);
});
it('should not login jacques.dupont@mii.com, bad password', async () => {
const result = new HttpException('Invalid credentials', HttpStatus.UNAUTHORIZED);
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' };
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'validateUser').mockImplementation(async (): Promise<any> => result);
expect(await service.validateUser(loginDto)).toBe(result);
});
it('should not login jacques.dupont@mii.com, username does not exist', async () => {
const result = new HttpException('Invalid credentials', HttpStatus.UNAUTHORIZED);
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' };
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'validateUser').mockImplementation(async (): Promise<any> => result);
expect(await service.validateUser(loginDto)).toBe(result);
});
......
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
const options = new DocumentBuilder().setTitle('RAM').setDescription('RAM API description').setVersion('1.0').build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('api', app, document);
......
import { Type } from 'class-transformer';
import { ArrayNotEmpty, IsNotEmpty, ValidateNested } from 'class-validator';
import { Address } from '../schemas/address.schema';
import { Week } from '../schemas/week.schema';
export class CreateStructureDto {
id: number;
numero: number;
dateDeCreation: string;
derniereModification: string;
nomDeLusager: string;
votreStructureEstElle: string;
nomDeVotreStructure: string;
numero: string;
createdAt: string;
updatedAt: string;
@IsNotEmpty()
structureRepresentation: string;
@IsNotEmpty()
structureName: string;
@ArrayNotEmpty()
structureType: string[];
@IsNotEmpty()
description: string;
activitesMaintenuesDansLeCadreDuConfinement: string;
n: string;
voie: string;
telephone: string;
courriel: string;
siteWeb: string;
@ValidateNested({ each: true })
@Type(() => Address)
address: Address;
@IsNotEmpty()
contactPhone: string;
@IsNotEmpty()
contactMail: string;
website: string;
facebook: string;
twitter: string;
instagram: string;
civilite: string;
nom: string;
prenom: string;
gender: string;
contactName: string;
contactSurname: string;
fonction: string;
accessibilitePersonnesAMobiliteReduitePmr: string;
modalitesDacces: string[];
labelsEtQualifications: string[];
publicsAcceptes: string[];
fermeturesExceptionnelles: string;
jaccompagneLesUsagersDansLeursDemarchesEnLigne: boolean;
accompagnementDesDemarches: string[];
autresAccompagnements: string;
lesCompetencesDeBase: string[];
accesAuxDroits: string[];
insertionSocialeEtProfessionnelle: string[];
aideALaParentalite: string[];
cultureEtSecuriteNumerique: string[];
wifiEnAccesLibre: boolean;
nbComputers: boolean;
nombre: string;
tablettes: boolean;
bornesNumeriques: boolean;
imprimantes: boolean;
precisionsSiNecessaire: string;
statutJuridique: string;
appartenezVousAUnReseauDeMediation: string;
precisezLequel: string;
idDeLitemStructureDansDirectus: string;
statutDeLitemStructureDansDirectus: string;
idDeLitemOffreDansDirectus: string;
statut: string;
typeDeStructure: string[];
commune: string;
lockdownActivity: string;
pmrAccess: boolean;
publicsAccompaniment: string[];
proceduresAccompaniment: string[];
@ArrayNotEmpty()
accessModality: string[];
documentsMeeting: string;
labelsQualifications: string[];
@ArrayNotEmpty()
publics: string[];
nbComputers: number;
nbPrinters: number;
nbTablets: number;
nbNumericTerminal: number;
exceptionalClosures: string;
equipmentsAndServices: string[];
hours: Week;
equipmentsDetails: string;
equipmentsAccessType: string[];
baseSkills: string[];
accessRight: string[];
parentingHelp: string[];
socialAndProfessional: string[];
digitalCultureSecurity: string[];
coord: number[];
}
import { SchemaFactory } from '@nestjs/mongoose';
import { IsNotEmpty } from 'class-validator';
export type AddressDocument = Address & Document;
export class Address {
numero: string;
@IsNotEmpty()
street: string;
@IsNotEmpty()
commune: string;
}
export const AddressSchema = SchemaFactory.createForClass(Address);
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';
import { Address } from './address.schema';
import { Week } from './week.schema';
export type StructureDocument = Structure & Document;
......@@ -13,43 +14,36 @@ export class Structure {
numero: string;
@Prop()
dateDeCreation: string;
createdAt: string;
@Prop()
derniereModification: string;
updatedAt: string;
@Prop()
nomDeLusager: string;
structureRepresentation: string;
@Prop()
votreStructureEstElle: string;
structureName: string;
@Prop()
nomDeVotreStructure: string;
structureType: string[];
@Prop()
description: string;
@Prop()
activitesMaintenuesDansLeCadreDuConfinement: string;
lockdownActivity: string;
@Prop()
n: string;
address: Address;
@Prop()
voie: string;
contactPhone: string;
@Prop()
address: string;
@Prop()
telephone: string;
@Prop()
courriel: string;
contactMail: string;
@Prop()
siteWeb: string;
website: string;
@Prop()
facebook: string;
......@@ -61,91 +55,76 @@ export class Structure {
instagram: string;
@Prop()
civilite: string;
gender: string;
@Prop()
nom: string;
contactName: string;
@Prop()
prenom: string;
contactSurname: string;
@Prop()
fonction: string;
@Prop()
accessibilitePersonnesAMobiliteReduitePmr: string;
pmrAccess: boolean;
@Prop()
modalitesDacces: string[];
accessModality: string[];
@Prop()
labelsEtQualifications: string[];
documentsMeeting: string;
@Prop()
publicsAcceptes: string[];
labelsQualifications: string[];
@Prop()
fermeturesExceptionnelles: string;
publics: string[];
@Prop()
jaccompagneLesUsagersDansLeursDemarchesEnLigne: boolean;
exceptionalClosures: string;
@Prop()
accompagnementDesDemarches: string[];
publicsAccompaniment: string[];
@Prop()
autresAccompagnements: string;
proceduresAccompaniment: string[];
@Prop()
lesCompetencesDeBase: string[];
baseSkills: string[];
@Prop()
accesAuxDroits: string[];
accessRight: string[];
@Prop()
insertionSocialeEtProfessionnelle: string[];
socialAndProfessional: string[];
@Prop()
aideALaParentalite: string[];
parentingHelp: string[];
@Prop()
cultureEtSecuriteNumerique: string[];
digitalCultureSecurity: string[];
@Prop()
equipementsEtServicesProposes: string[];
equipmentsDetails: string;
@Prop()
nbComputers: number;
@Prop()
precisionsSiNecessaire: string;
equipmentsAccessType: string[];
@Prop()
statutJuridique: string;
equipmentsAndServices: string[];
@Prop()
appartenezVousAUnReseauDeMediation: string;
@Prop()
precisezLequel: string;
@Prop()
idDeLitemStructureDansDirectus: string;
@Prop()
statutDeLitemStructureDansDirectus: string;
@Prop()
idDeLitemOffreDansDirectus: string;
nbComputers: number;
@Prop()
statut: string;
nbPrinters: number;
@Prop()
typeDeStructure: string[];
nbTablets: number;
@Prop()
commune: string;
nbNumericTerminal: number;
@Prop()
hours: Week;
......
import { Body, Controller, Get, Param, Post, Query, Req } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, Query } from '@nestjs/common';
import { CreateStructureDto } from './dto/create-structure.dto';
import { QueryStructure } from './dto/query-structure.dto';
import { Structure } from './schemas/structure.schema';
......@@ -18,6 +18,11 @@ export class StructuresController {
return this.structureService.search(query.query, body ? body.filters : null);
}
@Post(':id')
public async update(@Param('id') id: number, @Body() body: CreateStructureDto) {
return this.structureService.update(id, body);
}
@Get()
public async findAll(): Promise<Structure[]> {
return this.structureService.findAll();
......@@ -26,18 +31,26 @@ export class StructuresController {
@Get('count')
public async countCategories(): Promise<Array<{ id: string; count: number }>> {
const data = await Promise.all([
this.structureService.countByStructureKey('accesAuxDroits'),
this.structureService.countByStructureKey('aideALaParentalite'),
this.structureService.countByStructureKey('cultureEtSecuriteNumerique'),
this.structureService.countByStructureKey('insertionSocialeEtProfessionnelle'),
this.structureService.countByStructureKey('accompagnementDesDemarches'),
this.structureService.countByStructureKey('labelsEtQualifications'),
this.structureService.countByStructureKey('publicsAcceptes'),
this.structureService.countByStructureKey('modalitesDacces'),
this.structureService.countByStructureKey('lesCompetencesDeBase'),
this.structureService.countByStructureKey('equipementsEtServicesProposes'),
this.structureService.countByStructureKey('proceduresAccompaniment'),
this.structureService.countByStructureKey('accessRight'),
this.structureService.countByStructureKey('baseSkills'),
this.structureService.countByStructureKey('parentingHelp'),
this.structureService.countByStructureKey('digitalCultureSecurity'),
this.structureService.countByStructureKey('socialAndProfessional'),
this.structureService.countByStructureKey('publicsAccompaniment'),
this.structureService.countByStructureKey('labelsQualifications'),
this.structureService.countByStructureKey('publics'),
this.structureService.countByStructureKey('accessModality'),
this.structureService.countByStructureKey('equipmentsAndServices'),
]);
// Return a concat of all arrays
return data.reduce((a, b) => [...a, ...b]);
}
@Get(':id')
public async find(@Param('id') id: number) {
return this.structureService.findOne(id);
}
}
import { HttpService, Injectable } from '@nestjs/common';
import { HttpException, HttpService, Injectable, HttpStatus } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Observable } from 'rxjs';
......@@ -69,15 +69,25 @@ export class StructuresService {
return this.structureModel.find().exec();
}
public async update(idStructure: number, structure: CreateStructureDto): Promise<Structure> {
const result = await this.structureModel.update({ id: idStructure }, structure);
if (!result) {
throw new HttpException('Invalid structure id', HttpStatus.BAD_REQUEST);
}
return structure;
}
public findOne(idParam: number): Promise<Structure> {
return this.structureModel.findOne({ id: idParam }).exec();
}
/**
* Get structures positions and add marker corresponding to those positons on the map
*/
private getStructurePosition(structure: Structure): Promise<Structure> {
return new Promise((resolve) => {
this.getCoord(structure.n, structure.voie, structure.commune).subscribe(
this.getCoord(structure.address.numero, structure.address.street, structure.address.commune).subscribe(
(res) => {
const address = res.data.features[0];
structure.address = structure.voie + ' - ' + address.properties.postcode + ' ' + address.properties.city;
structure.coord = address.geometry.coordinates;
resolve(structure);
},
......
import { HttpModule, HttpService } from '@nestjs/common';
import { HttpModule } from '@nestjs/common';
import { getModelToken } from '@nestjs/mongoose';
import { Test, TestingModule } from '@nestjs/testing';
import { ConfigurationModule } from '../configuration/configuration.module';
......
import { Body, Controller, Get, Param, Post, Query, Req, Request, UseGuards } from '@nestjs/common';
import { Body, Controller, Get, Param, Post, Query, Request, UseGuards } from '@nestjs/common';
import { ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { PasswordChangeDto } from './change-password.dto';
......
......@@ -39,14 +39,14 @@ describe('UsersService', () => {
email: 'jacques.dupont@mii.com',
password: '$2a$12$vLQjJ9zAWyUwiXLeQDa6w.yazDArYIpf2WnQF1jRHOjBxADEjUEA3',
};
const userDto: CreateUserDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' };
const userDto: CreateUserDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'create').mockImplementation(async (): Promise<User> => result);
expect(await service.create(userDto)).toBe(result);
});
it('User should not be created, already exist', async () => {
const result = new HttpException('User already exists', HttpStatus.BAD_REQUEST);
const userDto: CreateUserDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' };
const userDto: CreateUserDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'create').mockImplementation(async (): Promise<any> => result);
expect(await service.create(userDto)).toBe(result);
});
......@@ -56,7 +56,7 @@ describe('UsersService', () => {
'Weak password, it must contain ne lowercase alphabetical character, one uppercase alphabetical character, one numeric character, one special character and be eight characters or longer',
HttpStatus.UNPROCESSABLE_ENTITY
);
const userDto: CreateUserDto = { email: 'jacques.dupont@mii.com', password: 'test' };
const userDto: CreateUserDto = { email: 'jacques.dupont@mii.com', password: 'test' }; //NOSONAR
jest.spyOn(service, 'create').mockImplementation(async (): Promise<any> => result);
expect(await service.create(userDto)).toBe(result);
});
......@@ -72,21 +72,21 @@ describe('UsersService', () => {
password: '$2a$12$vLQjJ9zAWyUwiXLeQDa6w.yazDArYIpf2WnQF1jRHOjBxADEjUEA3',
role: 0,
};
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' };
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'findByLogin').mockImplementation(async (): Promise<User> => result);
expect(await service.findByLogin(loginDto)).toBe(result);
});
it('user does not exist, should be unauthorized issue', async () => {
const result: HttpException = new HttpException('Invalid credentials', HttpStatus.UNAUTHORIZED);
const loginDto: LoginDto = { email: 'jean.dupont@mii.com', password: 'test1A!!' };
const loginDto: LoginDto = { email: 'jean.dupont@mii.com', password: 'test1A!!' }; //NOSONAR
jest.spyOn(service, 'findByLogin').mockImplementation(async (): Promise<any> => result);
expect(await service.findByLogin(loginDto)).toBe(result);
});
it('wrong password, should be unauthorized issue', async () => {
const result: HttpException = new HttpException('Invalid credentials', HttpStatus.UNAUTHORIZED);
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!!' };
const loginDto: LoginDto = { email: 'jacques.dupont@mii.com', password: 'test1A!!!' }; //NOSONAR
jest.spyOn(service, 'findByLogin').mockImplementation(async (): Promise<any> => result);
expect(await service.findByLogin(loginDto)).toBe(result);
});
......
......@@ -47,7 +47,7 @@ export class UsersService {
* @param password string
*/
private isStrongPassword(password: string): boolean {
const strongRegex = new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})');
const strongRegex = new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})'); //NOSONAR
return strongRegex.test(password);
}
......