diff --git a/package.json b/package.json index d16bedaea13436f7587b643d9db4448bd379df37..8f5f493a90cdbbcf47cf896927b7df07e5ee4616 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,10 @@ "prebuild": "rimraf dist", "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", - "start": "nest start", + "start": "cross-env NODE_ENV=dev nest start", "start:dev": "cross-env NODE_ENV=dev nest start --watch", - "start:debug": "nest start --debug --watch", - "start:prod": "node dist/main", + "start:debug": "cross-env NODE_ENV=dev nest start --debug --watch", + "start:prod": "cross-env NODE_ENV=prod node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", diff --git a/src/app.module.ts b/src/app.module.ts index 525febf15237651fc7a66eddfdf9b53f1d73a9ef..e794431d67f12d769b4c16cfd6d8d637472b597e 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; -import { mongodb } from './config'; +import config from './config'; import { PeopleModule } from './people/people.module'; import { GroupsModule } from './groups/groups.module'; import { InternshipsModule } from './internships/internships.module'; @@ -10,7 +10,7 @@ import { InternshipsModule } from './internships/internships.module'; PeopleModule, GroupsModule, InternshipsModule, - MongooseModule.forRoot(mongodb.uri), + MongooseModule.forRoot(config.mongodb.uri), ], }) export class AppModule {} diff --git a/src/config/config.prod.json b/src/config/config.prod.json new file mode 100644 index 0000000000000000000000000000000000000000..221da47e94f8ee7466bfef5535006d094832ff04 --- /dev/null +++ b/src/config/config.prod.json @@ -0,0 +1,9 @@ +{ + "server": { + "uri": "localhost", + "port": 3001 + }, + "mongodb": { + "uri": "mongodb://localhost:27017/internship-manager" + } +} diff --git a/src/config/index.ts b/src/config/index.ts index 3bf48c8fc881bf8611016389c8321c7cfef1f121..916f17f78890c853628a00a582386df2355940fb 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,8 +1,32 @@ -import * as _config from './config.json'; import { IConfig } from './config.model'; +import { readFileSync } from 'fs'; +import * as path from 'path'; -const config = _config as IConfig; +// Store file local path in var for lisibility +const CONFIG_DEV = 'config.json'; +const CONFIG_PROD = 'config.prod.json'; -export const server = config.server; -export const mongodb = config.mongodb; +let config; +// Load config based on env +switch (process.env.NODE_ENV) { + case 'dev': + // Load 'dev' config + config = JSON.parse( + readFileSync(path.join(__dirname, CONFIG_DEV), 'utf-8'), + ) as IConfig; + break; + case 'prod': + // Load 'prod' config + config = JSON.parse( + readFileSync(path.join(__dirname, CONFIG_PROD), 'utf-8'), + ) as IConfig; + break; + default: + // This shouldn't happen + console.log('\x1b[31mFATAL: Cannot load config.\x1b[0m'); + config = null; + break; +} + +// Export config export default config; diff --git a/src/internships/dao/internships.dao.ts b/src/internships/dao/internships.dao.ts index 8a573c1bad0e2a9034c4768d8fe7308122cbed84..be98077f9a24108ed27edabb60daf7cfbcf5ed93 100644 --- a/src/internships/dao/internships.dao.ts +++ b/src/internships/dao/internships.dao.ts @@ -2,8 +2,7 @@ import { Injectable, NotFoundException } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; import { CONFLICT } from 'src/shared/HttpError'; -import { STATE_1 } from 'src/shared/InternshipState'; -import { STATUS_NOK } from 'src/shared/InternshipStatus'; +import { STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION } from 'src/shared/InternshipState'; import { CreateInternshipDto } from '../dto/create-internship.dto'; import { InternshipDto } from '../dto/internship.dto'; import { Internship } from '../schemas/internship.schema'; @@ -61,7 +60,10 @@ export class InternshipDao { // Check if information modification is allowed -> current state is information input by student and updating is allowed const decoratedInternship = this.toInternshipDtoWithTracking(internship); this._internshipModel.findOneAndReplace( - { studentId, 'tracking.state': STATE_1, 'tracking.status': STATUS_NOK }, + { + studentId, + 'tracking.state': STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION, + }, decoratedInternship, { new: true, @@ -89,7 +91,6 @@ export class InternshipDao { ...createInternshipDto, tracking: { state: 'state-1', - status: 'nok', }, }; }; diff --git a/src/internships/dto/nested-create/tracking.dto.ts b/src/internships/dto/nested-create/tracking.dto.ts index b14354b591d24696d9b97b8c697693785fb7efda..868c9b0046b1f39e1b6747e66144d08188f3cb11 100644 --- a/src/internships/dto/nested-create/tracking.dto.ts +++ b/src/internships/dto/nested-create/tracking.dto.ts @@ -1,11 +1,35 @@ -import { IsString, IsNotEmpty } from 'class-validator'; +import { IsString, IsNotEmpty, IsBoolean, IsOptional } from 'class-validator'; export class TrackingDto { @IsString() @IsNotEmpty() state: string; + @IsBoolean() + @IsOptional() + studentEntersInternshipInformation?: boolean; + + @IsBoolean() + @IsOptional() + responsibleAcceptsInternshipInformation?: boolean; + @IsString() - @IsNotEmpty() - status: string; + @IsOptional() + secretaryEstablishesInternshipAgreement?: string; + + @IsString() + @IsOptional() + studentSignsInternshipAgreement?: string; + + @IsString() + @IsOptional() + responsibleSignsInternshipAgreement?: string; + + @IsString() + @IsOptional() + companySignsInternshipAgreement?: string; + + @IsString() + @IsOptional() + deanSignsInternshipAgreement?: string; } diff --git a/src/internships/entities/nested-entities/tracking.entity.ts b/src/internships/entities/nested-entities/tracking.entity.ts index a41f5e7792efcf12744149664b12021dfaf62485..a13fd5b8288ff3cca0cd9c226766dafcdda29f94 100644 --- a/src/internships/entities/nested-entities/tracking.entity.ts +++ b/src/internships/entities/nested-entities/tracking.entity.ts @@ -1,6 +1,12 @@ export class TrackingEntity { state: string; - status: string; + studentEntersInternshipInformation?: boolean; + responsibleAcceptsInternshipInformation?: boolean; + secretaryEstablishesInternshipAgreement?: string; + studentSignsInternshipAgreement?: string; + responsibleSignsInternshipAgreement?: string; + companySignsInternshipAgreement?: string; + deanSignsInternshipAgreement?: string; constructor(partial: Partial<TrackingEntity>) { Object.assign(this, partial); diff --git a/src/internships/internships.controller.ts b/src/internships/internships.controller.ts index 0c43ac8199e2e8e52180b0d44db79b8ddc72df21..70c798990da55caabe07b1915aec4b57ce78b633 100644 --- a/src/internships/internships.controller.ts +++ b/src/internships/internships.controller.ts @@ -8,7 +8,7 @@ import { Body, UseInterceptors, } from '@nestjs/common'; -import { BAD_TRACKING_STATE, CUSTOM } from 'src/shared/HttpError'; +import { BAD_TRACKING_STATE } from 'src/shared/HttpError'; import * as InternshipStates from 'src/shared/InternshipState'; import { HttpInterceptor } from '../interceptors/http.interceptor'; import { CreateInternshipDto } from './dto/create-internship.dto'; @@ -52,7 +52,7 @@ export class InternshipsController { @Param() params: { studentId: string }, @Body() body: { state: string; content: string }, ) { - if (!InternshipStates.isAllowedState(body.state)) + if (!InternshipStates.isStateValid(body.state)) throw BAD_TRACKING_STATE(body.state); // Treat request and update tracking -> implement service + dao } diff --git a/src/internships/schemas/nested-schemas/tracking.schema.ts b/src/internships/schemas/nested-schemas/tracking.schema.ts index 95ce881cb47b0b9fcfde0b7a6ee14ee62fc86e50..1d22866c567d511ce84aaf85c16dfc0fcf123b08 100644 --- a/src/internships/schemas/nested-schemas/tracking.schema.ts +++ b/src/internships/schemas/nested-schemas/tracking.schema.ts @@ -4,10 +4,28 @@ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; // Nested Schema @Schema({ _id: false }) export class Tracking extends Document { - @Prop({ type: String, required: true, trim: true }) - status: string; - @Prop({ type: String, required: true, trim: true }) state: string; + + @Prop({ type: Boolean, required: false, trim: true }) + studentEntersInternshipInformation?: boolean; + + @Prop({ type: Boolean, required: false, trim: true }) + responsibleAcceptsInternshipInformation?: boolean; + + @Prop({ type: String, required: false, trim: true }) + secretaryEstablishesInternshipAgreement?: string; + + @Prop({ type: String, required: false, trim: true }) + studentSignsInternshipAgreement?: string; + + @Prop({ type: String, required: false, trim: true }) + responsibleSignsInternshipAgreement?: string; + + @Prop({ type: String, required: false, trim: true }) + companySignsInternshipAgreement?: string; + + @Prop({ type: String, required: false, trim: true }) + deanSignsInternshipAgreement?: string; } export const TrackingSchema = SchemaFactory.createForClass(Tracking); diff --git a/src/main.ts b/src/main.ts index d8f8ddbbdd561fb76405dc4998154d4a185dad08..73418ec40e7590e32d10c7c56387f31a8057b1fd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,15 +1,21 @@ import { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; +import { exit } from 'process'; import { AppModule } from './app.module'; -import { server } from './config'; +import config from './config'; async function bootstrap() { const app = await NestFactory.create(AppModule); const env = process.env.NODE_ENV; if (env === 'dev') { app.enableCors(); - } else { + } else if (env === 'prod') { // enableCors for SPECIFIC origin only, aka the way it's supposed to be + } else { + console.log( + '\x1b[31mFATAL: Invalid application environment.\nDid you read the \x1b[4mREADME\x1b[0m\x1b[31m ?\x1b[0m', + ); + exit(-1); } await app.useGlobalPipes( new ValidationPipe({ @@ -17,6 +23,6 @@ async function bootstrap() { forbidNonWhitelisted: true, }), ); - await app.listen(server.port); + await app.listen(config.server.port); } bootstrap(); diff --git a/src/shared/InternshipState.ts b/src/shared/InternshipState.ts index 26b492d5c57b035d2c916f9daaa94cb911bfb899..8d8a06e8505084f641dfd93eb42d37668622699e 100644 --- a/src/shared/InternshipState.ts +++ b/src/shared/InternshipState.ts @@ -1,20 +1,27 @@ -export const STATE_1 = 'state-1'; -export const STATE_2 = 'state-2'; -export const STATE_3 = 'state-3'; -export const STATE_4 = 'state-4'; -export const STATE_5 = 'state-5'; -export const STATE_6 = 'state-6'; -export const STATE_7 = 'state-7'; +export const STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION = + 'student-enters-internship-information'; +export const STATE_RESPONSIBLE_ACCEPTS_INTERNSHIP_INFORMATION = + 'responsible-accepts-internship-information'; +export const STATE_SECRETARY_ESTABLISHES_INTERNSHIP_AGREEMENT = + 'secretary-establishes-internship-agreement'; +export const STATE_STUDENT_SIGNS_INTERNSHIP_AGREEMENT = + 'student-signs-internship-agreement'; +export const STATE_RESPONSIBLE_SIGNS_INTERNSHIP_AGREEMENT = + 'responsible-signs-internship-agreement'; +export const STATE_COMPANY_SIGNS_INTERNSHIP_AGREEMENT = + 'company-signs-internship-agreement'; +export const STATE_DEAN_SIGNS_INTERNSHIP_AGREEMENT = + 'dean-signs-internship-agreement'; export const STATES = [ - STATE_1, - STATE_2, - STATE_3, - STATE_4, - STATE_5, - STATE_6, - STATE_7, + STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION, + STATE_RESPONSIBLE_ACCEPTS_INTERNSHIP_INFORMATION, + STATE_SECRETARY_ESTABLISHES_INTERNSHIP_AGREEMENT, + STATE_STUDENT_SIGNS_INTERNSHIP_AGREEMENT, + STATE_RESPONSIBLE_SIGNS_INTERNSHIP_AGREEMENT, + STATE_COMPANY_SIGNS_INTERNSHIP_AGREEMENT, + STATE_DEAN_SIGNS_INTERNSHIP_AGREEMENT, ]; -export const isAllowedState = (potentialState: string): boolean => +export const isStateValid = (potentialState: string): boolean => STATES.includes(potentialState); diff --git a/src/shared/InternshipStatus.ts b/src/shared/InternshipStatus.ts deleted file mode 100644 index d375607c3ccff50325fdffa0e8b280aa0aaa9831..0000000000000000000000000000000000000000 --- a/src/shared/InternshipStatus.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const STATUS_OK = 'ok'; -export const STATUS_NOK = 'nok'; - -export type InternshipState = 'ok' | 'nok';