From 951f51e7e919f5da633b4bebc0cf4c0c9cbf14d0 Mon Sep 17 00:00:00 2001
From: FORESTIER Fabien <fabien.forestier@soprasteria.com>
Date: Fri, 22 Mar 2019 15:44:32 +0100
Subject: [PATCH] Remove variable env conf from environment files and conf.json
 from the assets, add possibility of build a release

---
 .gitlab-ci.yml                                | 21 ++---
 Dockerfile                                    |  4 +-
 angular.json                                  | 83 ++++++-------------
 config/config-dev.json                        | 12 +++
 config/config-rec.json                        | 12 +++
 docker-compose.yml                            |  3 +-
 package.json                                  |  8 +-
 src/app/app.module.ts                         | 16 ++++
 src/app/core/services/app-config.service.ts   | 30 +++++++
 src/app/core/services/email.service.ts        |  6 +-
 src/app/core/services/index.ts                |  8 +-
 src/app/core/services/matomo.service.ts       |  4 +-
 .../services/credits.service.ts               |  4 +-
 .../services/organizations.service.ts         |  4 +-
 .../services/elasticsearch.service.ts         |  6 +-
 .../geosource/services/resources.service.ts   |  6 +-
 .../user/services/user-services.service.ts    | 14 ++--
 src/app/user/services/user.service.ts         | 24 +++---
 src/assets/config/config.json                 | 12 +++
 src/environments/environment.dev.ts           | 55 ------------
 ...t.staging.ts => environment.production.ts} | 20 +----
 src/environments/environment.ts               | 15 ----
 src/main.ts                                   | 16 +++-
 23 files changed, 186 insertions(+), 197 deletions(-)
 create mode 100644 config/config-dev.json
 create mode 100644 config/config-rec.json
 create mode 100644 src/app/core/services/app-config.service.ts
 create mode 100644 src/assets/config/config.json
 delete mode 100644 src/environments/environment.dev.ts
 rename src/environments/{environment.staging.ts => environment.production.ts} (73%)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 07101f98..9157e7ad 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,5 @@
 stages:
-  - test
+  # - test
   - build
   - deploy
   - post-deploy
@@ -20,21 +20,20 @@ build_development:
   script:
     - export TAG=dev
     - export NGINX_PORT=8081
-    - docker-compose build --build-arg env=dev nginx-app
+    - docker-compose build nginx-app --build-arg build-conf=dev
     - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
     - docker-compose push
 
-build_staging:
+build_release:
   stage: build
-  tags:
-    - build
   only:
-    - development
-  when: manual
+    - tags
+  except:
+    - /^(?!master).+@/
   script:
-    - export TAG=staging
-    - export NGINX_PORT=8080
-    - docker-compose build --build-arg env=staging nginx-app
+    - export TAG=$(echo $CI_COMMIT_TAG | sed 's/v//g')
+    - export NGINX_PORT=8081
+    - docker-compose build nginx-app --build-arg build-conf=prod
     - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
     - docker-compose push
 
@@ -49,6 +48,7 @@ deploy_development:
     - export MATOMO_SERVER_URL=https://matomo-intothesky.alpha.grandlyon.com
     - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
     - docker-compose pull
+    - cp ./config/config-dev.json ./config/config.json
     - docker-compose --project-name portail-data-${TAG} up -d
   environment:
     name: development
@@ -66,6 +66,7 @@ deploy_staging:
   - export MATOMO_SERVER_URL=https://matomo-intothesky.alpha.grandlyon.com
   - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
   - docker-compose pull
+  - cp ./config/config-rec.json ./config/config.json
   - docker-compose --project-name portail-data-${TAG} up -d
   environment:
     name: staging
diff --git a/Dockerfile b/Dockerfile
index 07c62d14..eca92cca 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,10 +12,10 @@ COPY . /app
 # Launch postinstall script (to include crypto module)
 RUN npm run postinstall
 
-ARG env
+ARG build-conf
 
 # Building the Angular app /dist i18n
-RUN npm run build-i18n:${env}
+RUN npm run build-i18n:${build-conf}
 
 # Stage 1, based on Nginx, to have only the compiled app
 FROM nginx
diff --git a/angular.json b/angular.json
index 186c8e50..b884911f 100644
--- a/angular.json
+++ b/angular.json
@@ -39,12 +39,10 @@
               "i18nFile": "src/i18n/messages.fr.xlf",
               "i18nFormat": "xlf",
               "i18nLocale": "fr",
-              "fileReplacements": [
-                {
-                  "replace": "src/i18n/traductions.ts",
-                  "with": "src/i18n/traductions.fr.ts"
-                }
-              ]
+              "fileReplacements": [{
+                "replace": "src/i18n/traductions.ts",
+                "with": "src/i18n/traductions.fr.ts"
+              }]
             },
             "aot-en": {
               "optimization": false,
@@ -60,27 +58,27 @@
               "i18nFormat": "xlf",
               "i18nLocale": "en"
             },
-            "production": {
-              "optimization": true,
+            "development-en": {
+              "optimization": false,
               "outputHashing": "all",
-              "sourceMap": false,
+              "sourceMap": true,
               "extractCss": false,
               "namedChunks": false,
               "aot": true,
               "extractLicenses": true,
               "vendorChunk": false,
-              "buildOptimizer": true,
-              "fileReplacements": [
-                {
-                  "replace": "src/environments/environment.ts",
-                  "with": "src/environments/environment.staging.ts"
-                }
-              ]
+              "buildOptimizer": false,
+              "fileReplacements": [],
+              "outputPath": "dist/en",
+              "i18nFile": "src/i18n/messages.en.xlf",
+              "i18nFormat": "xlf",
+              "i18nLocale": "en",
+              "baseHref": "/en/"
             },
             "development-fr": {
               "optimization": false,
               "outputHashing": "all",
-              "sourceMap": false,
+              "sourceMap": true,
               "extractCss": false,
               "namedChunks": false,
               "aot": true,
@@ -88,10 +86,6 @@
               "vendorChunk": false,
               "buildOptimizer": false,
               "fileReplacements": [
-                {
-                  "replace": "src/environments/environment.ts",
-                  "with": "src/environments/environment.dev.ts"
-                },
                 {
                   "replace": "src/i18n/traductions.ts",
                   "with": "src/i18n/traductions.fr.ts"
@@ -103,8 +97,8 @@
               "i18nLocale": "fr",
               "baseHref": "/fr/"
             },
-            "development-en": {
-              "optimization": false,
+            "production-en": {
+              "optimization": true,
               "outputHashing": "all",
               "sourceMap": false,
               "extractCss": false,
@@ -112,20 +106,18 @@
               "aot": true,
               "extractLicenses": true,
               "vendorChunk": false,
-              "buildOptimizer": false,
-              "fileReplacements": [
-                {
-                  "replace": "src/environments/environment.ts",
-                  "with": "src/environments/environment.dev.ts"
-                }
-              ],
+              "buildOptimizer": true,
+              "fileReplacements": [{
+                "replace": "src/environments/environment.ts",
+                "with": "src/environments/environment.production.ts"
+              }],
               "outputPath": "dist/en",
               "i18nFile": "src/i18n/messages.en.xlf",
               "i18nFormat": "xlf",
               "i18nLocale": "en",
               "baseHref": "/en/"
             },
-            "staging-fr": {
+            "production-fr": {
               "optimization": true,
               "outputHashing": "all",
               "sourceMap": false,
@@ -135,10 +127,9 @@
               "extractLicenses": true,
               "vendorChunk": false,
               "buildOptimizer": true,
-              "fileReplacements": [
-                {
+              "fileReplacements": [{
                   "replace": "src/environments/environment.ts",
-                  "with": "src/environments/environment.staging.ts"
+                  "with": "src/environments/environment.production.ts"
                 },
                 {
                   "replace": "src/i18n/traductions.ts",
@@ -150,28 +141,6 @@
               "i18nFormat": "xlf",
               "i18nLocale": "fr",
               "baseHref": "/fr/"
-            },
-            "staging-en": {
-              "optimization": true,
-              "outputHashing": "all",
-              "sourceMap": false,
-              "extractCss": false,
-              "namedChunks": false,
-              "aot": true,
-              "extractLicenses": true,
-              "vendorChunk": false,
-              "buildOptimizer": true,
-              "fileReplacements": [
-                {
-                  "replace": "src/environments/environment.ts",
-                  "with": "src/environments/environment.staging.ts"
-                }
-              ],
-              "outputPath": "dist/en",
-              "i18nFile": "src/i18n/messages.en.xlf",
-              "i18nFormat": "xlf",
-              "i18nLocale": "en",
-              "baseHref": "/en/"
             }
           }
         },
@@ -265,4 +234,4 @@
       "prefix": "app"
     }
   }
-}
\ No newline at end of file
+}
diff --git a/config/config-dev.json b/config/config-dev.json
new file mode 100644
index 00000000..2cb1d700
--- /dev/null
+++ b/config/config-dev.json
@@ -0,0 +1,12 @@
+{
+  "backendUrls": {
+    "organizations": "https://kong-dev.alpha.grandlyon.com/organizations",
+    "resources": "https://kong-dev.alpha.grandlyon.com/resources",
+    "credits": "https://kong-dev.alpha.grandlyon.com/credits",
+    "auth": "https://kong-dev.alpha.grandlyon.com/authentication/",
+    "middlewareLegacyAuth": "https://kong-dev.alpha.grandlyon.com/middleware-legacy/",
+    "email": "https://kong-dev.alpha.grandlyon.com/email",
+    "matomo": "https://kong-dev.alpha.grandlyon.com/analytics",
+    "elasticsearch": "https://kong-dev.alpha.grandlyon.com/es-consumer-aware"
+  }
+}
\ No newline at end of file
diff --git a/config/config-rec.json b/config/config-rec.json
new file mode 100644
index 00000000..240b119b
--- /dev/null
+++ b/config/config-rec.json
@@ -0,0 +1,12 @@
+{
+  "backendUrls": {
+    "organizations": "https://kong-rec.alpha.grandlyon.com/organizations",
+    "resources": "https://kong-rec.alpha.grandlyon.com/resources",
+    "credits": "https://kong-rec.alpha.grandlyon.com/credits",
+    "auth": "https://kong-rec.alpha.grandlyon.com/authentication/",
+    "middlewareLegacyAuth": "https://kong-rec.alpha.grandlyon.com/middleware-legacy/",
+    "email": "https://kong-rec.alpha.grandlyon.com/email",
+    "matomo": "https://kong-rec.alpha.grandlyon.com/analytics",
+    "elasticsearch": "https://kong-rec.alpha.grandlyon.com/es-consumer-aware"
+  }
+}
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index eced1698..ca6e913b 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,12 +2,13 @@ version: "3"
 
 services:
   nginx-app:
-    container_name: nginx-app-${TAG}
     restart: unless-stopped
     build: .
     image: registry.alpha.grandlyon.com/refonte-data/portail-data:${TAG}
     volumes: 
       - ./nginx.conf.template:/etc/nginx/nginx.conf.template
+      - ./config/config.json:/usr/share/nginx/html/fr/assets/config/config.json
+      - ./config/config.json:/usr/share/nginx/html/en/assets/config/config.json
     ports: 
       - ${NGINX_PORT}:8080
     command: >
diff --git a/package.json b/package.json
index ba1cacf7..306e9c2b 100644
--- a/package.json
+++ b/package.json
@@ -1,15 +1,15 @@
 {
   "name": "webapp",
-  "version": "2.10.0",
+  "version": "2.0.0",
   "license": "MIT",
   "scripts": {
     "ng": "ng",
     "start-aot-fr": "ng serve --configuration=aot-fr",
     "start-aot-en": "ng serve --configuration=aot-en",
     "build-i18n:dev": "for lang in en fr; do node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng build --configuration=development-$lang; done",
-    "build-i18n:staging": "for lang in en fr; do node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng build --configuration=staging-$lang; done",
-    "win-build-i18n:fr": "ng build --prod --build-optimizer --configuration=staging-fr",
-    "win-build-i18n:en": "ng build --prod --build-optimizer --configuration=staging-en",
+    "build-i18n:prod": "for lang in en fr; do node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng build --configuration=production-$lang; done",
+    "win-build-i18n:fr": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng build --configuration=development-fr",
+    "win-build-i18n:en": "node --max_old_space_size=2048 ./node_modules/@angular/cli/bin/ng build --configuration=development-en",
     "win-build-i18n": "npm run win-build-i18n:en && npm run win-build-i18n:fr",
     "test": "ng test --browsers=Chrome --code-coverage=true",
     "test:ci": "ng test --browsers=ChromeHeadlessCI --code-coverage=true --watch=false",
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 56101c79..653c5eeb 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -11,6 +11,7 @@ import { Angulartics2Module } from 'angulartics2';
 import { Angulartics2Piwik } from 'angulartics2/piwik';
 import { UserModule } from './user/user.module';
 import { UserService } from './user/services';
+import { AppConfigService } from './core/services';
 
 // Function used by APP_INITIALIZER before the app start: init user info / statut (expect a promise)
 export function initUserService(authService: UserService) {
@@ -22,6 +23,15 @@ export function initUserService(authService: UserService) {
   };
 }
 
+export function initAppConfig(appConfigService: AppConfigService) {
+  return (): Promise<any> => {
+    return new Promise((resolve, reject) => {
+      appConfigService.load();
+      resolve();
+    });
+  };
+}
+
 @NgModule({
   declarations: [
     AppComponent,
@@ -43,6 +53,12 @@ export function initUserService(authService: UserService) {
       deps: [UserService],
       multi: true,
     },
+    {
+      provide: APP_INITIALIZER,
+      useFactory: initAppConfig,
+      deps: [AppConfigService],
+      multi: true,
+    },
   ],
   bootstrap: [AppComponent],
 })
diff --git a/src/app/core/services/app-config.service.ts b/src/app/core/services/app-config.service.ts
new file mode 100644
index 00000000..85f3dc02
--- /dev/null
+++ b/src/app/core/services/app-config.service.ts
@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+
+export class AppConfig {
+  backendUrls: {
+    organizations: string;
+    resources: string;
+    credits: string;
+    auth: string;
+    middlewareLegacyAuth: string;
+    email: string;
+    matomo: string;
+    elasticsearch: string;
+  };
+}
+
+export let APP_CONFIG: AppConfig;
+
+@Injectable()
+export class AppConfigService {
+
+  constructor() { }
+
+  public load() {
+    return new Promise((resolve, reject) => {
+      const conf = new AppConfig();
+      APP_CONFIG = Object.assign(conf, window['portailDataEnvConfig']);
+      resolve();
+    });
+  }
+}
diff --git a/src/app/core/services/email.service.ts b/src/app/core/services/email.service.ts
index 7f3b65de..cb2c0f65 100644
--- a/src/app/core/services/email.service.ts
+++ b/src/app/core/services/email.service.ts
@@ -1,7 +1,7 @@
 import { Injectable } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
-import { environment } from '../../../environments/environment';
 import { Email, Feedback } from '../models';
+import { APP_CONFIG } from './app-config.service';
 
 @Injectable()
 export class EmailService {
@@ -11,10 +11,10 @@ export class EmailService {
   ) {}
 
   send(email: Email) {
-    return this._httpClient.post(`${environment.backendUrls.email}/contact`, email);
+    return this._httpClient.post(`${APP_CONFIG.backendUrls.email}/contact`, email);
   }
 
   sendFeedback(feedback: Feedback) {
-    return this._httpClient.post(`${environment.backendUrls.email}/feedback`, feedback);
+    return this._httpClient.post(`${APP_CONFIG.backendUrls.email}/feedback`, feedback);
   }
 }
diff --git a/src/app/core/services/index.ts b/src/app/core/services/index.ts
index 0cb5d3d9..bbea3b75 100644
--- a/src/app/core/services/index.ts
+++ b/src/app/core/services/index.ts
@@ -5,7 +5,12 @@ import { NavigationHistoryService } from './navigation-history.service';
 import { StorageService } from './storage.service';
 import { EmailService } from './email.service';
 import { FileService } from './file-service';
-export { ErrorService, NotificationService, MatomoService, NavigationHistoryService, EmailService, FileService };
+import { AppConfigService } from './app-config.service';
+
+export {
+  ErrorService, NotificationService, MatomoService, NavigationHistoryService, EmailService, FileService,
+  AppConfigService,
+};
 
 // tslint:disable-next-line:variable-name
 export const CoreServices = [
@@ -16,4 +21,5 @@ export const CoreServices = [
   StorageService,
   EmailService,
   FileService,
+  AppConfigService,
 ];
diff --git a/src/app/core/services/matomo.service.ts b/src/app/core/services/matomo.service.ts
index d12972f8..470a4bac 100644
--- a/src/app/core/services/matomo.service.ts
+++ b/src/app/core/services/matomo.service.ts
@@ -3,9 +3,9 @@ import { IMatomoResponse } from '../models/matomo.model';
 import { Observable } from 'rxjs';
 import { HttpClient } from '@angular/common/http';
 import { map, catchError } from 'rxjs/operators';
-import { environment } from '../../../environments/environment';
 import { ErrorService } from './error.service';
 import { notificationMessages } from '../../../i18n/traductions';
+import { APP_CONFIG } from './app-config.service';
 
 @Injectable()
 export class MatomoService {
@@ -21,7 +21,7 @@ export class MatomoService {
     dateOneMonthAgo.setMonth(new Date().getMonth() - 1);
     const dateOneMonthAgoString = dateOneMonthAgo.toISOString().slice(0, 10);
 
-    const url = `${environment.backendUrls.matomo}/?module=API&method=Actions.getPageUrls` +
+    const url = `${APP_CONFIG.backendUrls.matomo}/?module=API&method=Actions.getPageUrls` +
       `&idSite=${window['siteId']}&format=json&period=range&date=${dateOneMonthAgoString}` +
       `,${dateNowString}` +
       `&segment=pageUrl=@${metadataId}/info`;
diff --git a/src/app/editorialisation/services/credits.service.ts b/src/app/editorialisation/services/credits.service.ts
index 9c6b605c..9a0a167f 100644
--- a/src/app/editorialisation/services/credits.service.ts
+++ b/src/app/editorialisation/services/credits.service.ts
@@ -1,8 +1,8 @@
 import { Injectable } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
-import { environment } from '../../../environments/environment';
 import { ICredit, Credit } from '../models';
 import { map } from 'rxjs/operators';
+import { APP_CONFIG } from '../../core/services/app-config.service';
 
 @Injectable()
 export class CreditsService {
@@ -12,7 +12,7 @@ export class CreditsService {
   ) { }
 
   getCredits() {
-    return this._httpClient.get<ICredit[]>(environment.backendUrls.credits).pipe(
+    return this._httpClient.get<ICredit[]>(APP_CONFIG.backendUrls.credits).pipe(
       map((creditsBack) => {
         const credits = [];
         creditsBack.forEach((credit) => {
diff --git a/src/app/editorialisation/services/organizations.service.ts b/src/app/editorialisation/services/organizations.service.ts
index 9f2b230f..ec00dc72 100644
--- a/src/app/editorialisation/services/organizations.service.ts
+++ b/src/app/editorialisation/services/organizations.service.ts
@@ -1,9 +1,9 @@
 import { Injectable } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
-import { environment } from '../../../environments/environment';
 import { IOrganization } from '../models';
 import { map } from 'rxjs/operators';
 import { Organization } from '../models/organization.model';
+import { APP_CONFIG } from '../../core/services/app-config.service';
 
 @Injectable()
 export class OrganizationsService {
@@ -13,7 +13,7 @@ export class OrganizationsService {
   ) { }
 
   getOrganizations() {
-    return this._httpClient.get<IOrganization[]>(environment.backendUrls.organizations).pipe(
+    return this._httpClient.get<IOrganization[]>(APP_CONFIG.backendUrls.organizations).pipe(
       map((organizationsBack) => {
         const organizations = [];
         organizationsBack.forEach((organization) => {
diff --git a/src/app/geosource/services/elasticsearch.service.ts b/src/app/geosource/services/elasticsearch.service.ts
index 6da4a0fb..5601a902 100644
--- a/src/app/geosource/services/elasticsearch.service.ts
+++ b/src/app/geosource/services/elasticsearch.service.ts
@@ -7,12 +7,13 @@ import {
 import { HttpClient } from '@angular/common/http';
 import { Observable, of } from 'rxjs';
 import { map, catchError } from 'rxjs/operators';
-import { ErrorService } from '../../core/services';
+import { ErrorService, AppConfigService } from '../../core/services';
 import { notificationMessages } from '../../../i18n/traductions';
 import { StorageService } from '../../core/services/storage.service';
 import { IPostsESOptions } from '../models/elasticsearch-options.model';
 import { Aggregation } from '../models/filter.model';
 import { scopesResearch } from '../models/scopes-research';
+import { APP_CONFIG } from '../../core/services/app-config.service';
 
 @Injectable()
 export class ElasticsearchService {
@@ -22,9 +23,10 @@ export class ElasticsearchService {
   constructor(
     private _errorService: ErrorService,
     private _storageService: StorageService,
+    private _appConfigService: AppConfigService,
     private _http: HttpClient,
   ) {
-    this.elasticSearchUrl = `${environment.backendUrls.elasticsearch}` +
+    this.elasticSearchUrl = `${APP_CONFIG.backendUrls.elasticsearch}` +
       '/_search?request_cache=true';
   }
 
diff --git a/src/app/geosource/services/resources.service.ts b/src/app/geosource/services/resources.service.ts
index 0f54c825..67d87853 100644
--- a/src/app/geosource/services/resources.service.ts
+++ b/src/app/geosource/services/resources.service.ts
@@ -1,9 +1,9 @@
 import { Injectable } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
-import { environment } from '../../../environments/environment';
 import { map } from 'rxjs/operators';
 import { Resource, IResource } from '../models';
 import { IResourceFormat, Format } from '../models/resource.model';
+import { APP_CONFIG } from '../../core/services/app-config.service';
 
 @Injectable()
 export class ResourcesService {
@@ -13,14 +13,14 @@ export class ResourcesService {
   ) { }
 
   getResources() {
-    return this._httpClient.get<IResource[]>(`${environment.backendUrls.resources}/resources`).pipe(
+    return this._httpClient.get<IResource[]>(`${APP_CONFIG.backendUrls.resources}/resources`).pipe(
       map((resourcesBack) => {
         return resourcesBack.map(r => new Resource(r));
       }));
   }
 
   getResourceFormats() {
-    return this._httpClient.get<IResourceFormat[]>(`${environment.backendUrls.resources}/resourceformats`).pipe(
+    return this._httpClient.get<IResourceFormat[]>(`${APP_CONFIG.backendUrls.resources}/resourceformats`).pipe(
       map((resourcesBack) => {
         const resources = [];
         resourcesBack.forEach((result) => {
diff --git a/src/app/user/services/user-services.service.ts b/src/app/user/services/user-services.service.ts
index 5e24c0f6..32315f27 100644
--- a/src/app/user/services/user-services.service.ts
+++ b/src/app/user/services/user-services.service.ts
@@ -5,7 +5,7 @@ import {
   IService, IRestrictedAccessDataset, IResource, RenewAccessToResourceResponse, AccessRequestToResourceResponse,
   DeleteAccessToRessourceResponse,
 } from '../models';
-import { environment } from '../../../environments/environment';
+import { APP_CONFIG } from '../../core/services/app-config.service';
 
 @Injectable()
 export class UserServicesService {
@@ -15,28 +15,28 @@ export class UserServicesService {
   ) { }
 
   getUserResources(): Observable<IResource[]> {
-    return this._http.get<IResource[]>(`${environment.backendUrls.middlewareLegacyAuth}user/resources`);
+    return this._http.get<IResource[]>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}user/resources`);
   }
 
   getRestrictedAccessDatasets(): Observable<IRestrictedAccessDataset[]> {
     // tslint:disable-next-line:max-line-length
-    return this._http.get<IRestrictedAccessDataset[]>(`${environment.backendUrls.middlewareLegacyAuth}restrictedAccessDatasets`);
+    return this._http.get<IRestrictedAccessDataset[]>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}restrictedAccessDatasets`);
   }
 
   getServices(): Observable<IService[]> {
-    return this._http.get<IService[]>(`${environment.backendUrls.middlewareLegacyAuth}services`);
+    return this._http.get<IService[]>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}services`);
   }
 
   requestAccessToResource(resource) {
     return this._http.post<AccessRequestToResourceResponse>(
-      `${environment.backendUrls.middlewareLegacyAuth}user/resources/add`,
+      `${APP_CONFIG.backendUrls.middlewareLegacyAuth}user/resources/add`,
       resource,
     );
   }
 
   renewAccessToResource(resource) {
     return this._http.post<RenewAccessToResourceResponse>(
-      `${environment.backendUrls.middlewareLegacyAuth}user/resources/renew`,
+      `${APP_CONFIG.backendUrls.middlewareLegacyAuth}user/resources/renew`,
       resource,
     );
   }
@@ -44,7 +44,7 @@ export class UserServicesService {
   deleteAccessToResource(resource) {
     return this._http.request<DeleteAccessToRessourceResponse>(
       'delete', // HTTP verb
-      `${environment.backendUrls.middlewareLegacyAuth}user/resources/delete`, // url
+      `${APP_CONFIG.backendUrls.middlewareLegacyAuth}user/resources/delete`, // url
       { body: resource }, // options
     );
   }
diff --git a/src/app/user/services/user.service.ts b/src/app/user/services/user.service.ts
index 8390d33d..9d65c8be 100644
--- a/src/app/user/services/user.service.ts
+++ b/src/app/user/services/user.service.ts
@@ -2,10 +2,10 @@ import { Injectable } from '@angular/core';
 import { HttpClient } from '@angular/common/http';
 import { Observable, Subject } from 'rxjs';
 import { IUserInfo, PasswordUpdateForm, User, ILoginResponse, LegacyAccount, IPasswordForgottenForm } from '../models';
-import { environment } from '../../../environments/environment';
 import { map, mergeMap, tap } from 'rxjs/operators';
 import * as JwtDecode from 'jwt-decode';
 import * as NodeRSA from 'node-rsa';
+import { APP_CONFIG } from '../../core/services/app-config.service';
 
 @Injectable()
 export class UserService {
@@ -76,7 +76,7 @@ export class UserService {
         },
       ),
       mergeMap(() => {
-        return this._http.post<ILoginResponse>(`${environment.backendUrls.auth}login/legacy`, form);
+        return this._http.post<ILoginResponse>(`${APP_CONFIG.backendUrls.auth}login/legacy`, form);
       }),
       map(
         (res) => {
@@ -96,7 +96,7 @@ export class UserService {
         },
       ),
       mergeMap(() => {
-        return this._http.post<any>(`${environment.backendUrls.middlewareLegacyAuth}user/`, form);
+        return this._http.post<any>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}user/`, form);
       }),
       map(
         (res) => {
@@ -107,15 +107,15 @@ export class UserService {
   }
 
   validateAccount(token: string) {
-    return this._http.post<any>(`${environment.backendUrls.middlewareLegacyAuth}user/validateAccount`, { token });
+    return this._http.post<any>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}user/validateAccount`, { token });
   }
 
   getUserInfo(): Observable<IUserInfo> {
-    return this._http.get<IUserInfo>(`${environment.backendUrls.auth}user`);
+    return this._http.get<IUserInfo>(`${APP_CONFIG.backendUrls.auth}user`);
   }
 
   updateUserInfo(info: IUserInfo): Observable<{ token: string }> {
-    return this._http.put<{ token: string }>(`${environment.backendUrls.auth}user/update`, info);
+    return this._http.put<{ token: string }>(`${APP_CONFIG.backendUrls.auth}user/update`, info);
   }
 
   updateUserPassword(passwordUpdateform: PasswordUpdateForm): Observable<void> {
@@ -129,13 +129,13 @@ export class UserService {
         },
       ),
       mergeMap(() => {
-        return this._http.put<void>(`${environment.backendUrls.middlewareLegacyAuth}user/updatePassword`, form);
+        return this._http.put<void>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}user/updatePassword`, form);
       }),
     );
   }
 
   forgotPassword(email: IPasswordForgottenForm): Observable<void> {
-    return this._http.post<void>(`${environment.backendUrls.middlewareLegacyAuth}passwordForgotten`, email).pipe(
+    return this._http.post<void>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}passwordForgotten`, email).pipe(
       map(
         (res) => {
           return;
@@ -146,7 +146,7 @@ export class UserService {
 
   isPasswordResetTokenValid(token: string): Observable<boolean> {
     // tslint:disable-next-line:max-line-length
-    return this._http.get<boolean>(`${environment.backendUrls.middlewareLegacyAuth}isPasswordResetTokenValid?token=${token}`);
+    return this._http.get<boolean>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}isPasswordResetTokenValid?token=${token}`);
   }
 
   resetPassword(token: string, password: string): Observable<void> {
@@ -160,13 +160,13 @@ export class UserService {
       ),
       mergeMap(() => {
         // tslint:disable-next-line:max-line-length
-        return this._http.put<void>(`${environment.backendUrls.middlewareLegacyAuth}user/resetPassword`, { token, password: encryptedPassword });
+        return this._http.put<void>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}user/resetPassword`, { token, password: encryptedPassword });
       }),
     );
   }
 
   deleteAccount(): Observable<void> {
-    return this._http.delete<any>(`${environment.backendUrls.middlewareLegacyAuth}user`).pipe(
+    return this._http.delete<any>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}user`).pipe(
       map(
         (res) => {
           return;
@@ -176,7 +176,7 @@ export class UserService {
   }
 
   getPublicKey(): Observable<any> {
-    return this._http.get<any>(`${environment.backendUrls.middlewareLegacyAuth}publicKey`).pipe(
+    return this._http.get<any>(`${APP_CONFIG.backendUrls.middlewareLegacyAuth}publicKey`).pipe(
       map(
         (res) => {
           return res.publicKey;
diff --git a/src/assets/config/config.json b/src/assets/config/config.json
new file mode 100644
index 00000000..8ec8c04c
--- /dev/null
+++ b/src/assets/config/config.json
@@ -0,0 +1,12 @@
+{
+  "backendUrls": {
+    "organizations": "http://localhost:3001/organizations",
+    "resources": "http://localhost:3003",
+    "credits": "http://localhost:3005/credits",
+    "auth": "http://localhost:3002/",
+    "middlewareLegacyAuth": "http://localhost:3004/",
+    "email": "http://localhost:3001/email",
+    "matomo": "https://matomo-intothesky.alpha.grandlyon.com",
+    "elasticsearch": "https://kong-dev.alpha.grandlyon.com/es-consumer-aware"
+  }
+}
\ No newline at end of file
diff --git a/src/environments/environment.dev.ts b/src/environments/environment.dev.ts
deleted file mode 100644
index 36073c7d..00000000
--- a/src/environments/environment.dev.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { AppRoutes } from '../app/routes';
-import * as packageJson from '../../package.json';
-
-// The file contents for the current environment will overwrite these during build.
-// The build system defaults to the dev environment which uses `environment.ts`
-// const servicesProxyUrl = 'https://data-intothesky.alpha.grandlyon.com';
-const kongBaseUrl = 'https://kong-dev.alpha.grandlyon.com';
-
-export const environment = {
-  version: (<any>packageJson).version,
-
-  production: true,
-  passwordMinLength: 6,
-
-  backendUrls: {
-    organizations: `${kongBaseUrl}/organizations`,
-    resources: `${kongBaseUrl}/resources`,
-    credits: `${kongBaseUrl}/credits`,
-    auth: `${kongBaseUrl}/authentication/`,
-    middlewareLegacyAuth: `${kongBaseUrl}/middleware-legacy/`,
-    email: `${kongBaseUrl}/email`,
-    matomo: `${kongBaseUrl}/analytics`,
-    elasticsearch: `${kongBaseUrl}/es-consumer-aware`,
-  },
-
-  enableEsFrontCache: false,
-
-  // Path to the built app in a particular language
-  angularAppHost: {
-    fr: '/fr',
-    en: '/en',
-  },
-
-  // CMS
-  cmsStaticPages: {},
-  cmsContent: {
-    categoryUniqueContent: 'static',
-    slugPostVideo: 'video-dgl',
-  },
-
-  // Map
-  defaultBaseLayer: 0,
-
-};
-
-// Use variable route names (AppRoutes.credits...) for each static page to attribute the corresponding
-// cms page in order to make sure that if the name of the route change in the config file (routes.ts),
-// the cms page will still be served.
-environment.cmsStaticPages[AppRoutes.accessibility.uri] = 'accessibilite';
-environment.cmsStaticPages[AppRoutes.documentation.uri] = 'utiliser-la-plateforme-data-du-grand-lyon';
-environment.cmsStaticPages[AppRoutes.siteMap.uri] = 'plan-du-site';
-environment.cmsStaticPages[AppRoutes.legalNotices.uri] = 'mentions-legales';
-environment.cmsStaticPages[AppRoutes.credits.uri] = 'credits';
-environment.cmsStaticPages[AppRoutes.cgu.uri] = 'conditions-generales-dutilisation';
-environment.cmsStaticPages[AppRoutes.beginners.uri] = 'le-coin-des-debutants';
diff --git a/src/environments/environment.staging.ts b/src/environments/environment.production.ts
similarity index 73%
rename from src/environments/environment.staging.ts
rename to src/environments/environment.production.ts
index 274f94fb..ad4a4a4a 100644
--- a/src/environments/environment.staging.ts
+++ b/src/environments/environment.production.ts
@@ -1,28 +1,14 @@
-import * as packageJson from '../../package.json';
 import { AppRoutes } from '../app/routes';
+import * as packageJson from '../../package.json';
 
 // The file contents for the current environment will overwrite these during build.
 // The build system defaults to the dev environment which uses `environment.ts`
-// const servicesProxyUrl = 'https://data-intothesky.alpha.grandlyon.com';
-const kongBaseUrl = 'https://kong-rec.alpha.grandlyon.com';
-
+// The list of which env maps to which file can be found in `.angular-cli.json`.
 export const environment = {
   version: (<any>packageJson).version,
 
   production: true,
   passwordMinLength: 6,
-
-  backendUrls: {
-    organizations: `${kongBaseUrl}/organizations`,
-    resources: `${kongBaseUrl}/resources`,
-    credits: `${kongBaseUrl}/credits`,
-    auth: `${kongBaseUrl}/authentication/`,
-    middlewareLegacyAuth: `${kongBaseUrl}/middleware-legacy/`,
-    email: `${kongBaseUrl}/email`,
-    matomo:`${kongBaseUrl}/analytics`,
-    elasticsearch: `${kongBaseUrl}/es-consumer-aware`,
-  },
-
   enableEsFrontCache: false,
 
   // Path to the built app in a particular language
@@ -47,8 +33,8 @@ export const environment = {
 // cms page in order to make sure that if the name of the route change in the config file (routes.ts),
 // the cms page will still be served.
 environment.cmsStaticPages[AppRoutes.accessibility.uri] = 'accessibilite';
-environment.cmsStaticPages[AppRoutes.siteMap.uri] = 'plan-du-site';
 environment.cmsStaticPages[AppRoutes.documentation.uri] = 'utiliser-la-plateforme-data-du-grand-lyon';
+environment.cmsStaticPages[AppRoutes.siteMap.uri] = 'plan-du-site';
 environment.cmsStaticPages[AppRoutes.legalNotices.uri] = 'mentions-legales';
 environment.cmsStaticPages[AppRoutes.credits.uri] = 'credits';
 environment.cmsStaticPages[AppRoutes.cgu.uri] = 'conditions-generales-dutilisation';
diff --git a/src/environments/environment.ts b/src/environments/environment.ts
index 27a46399..c2a846b8 100644
--- a/src/environments/environment.ts
+++ b/src/environments/environment.ts
@@ -4,26 +4,11 @@ import * as packageJson from '../../package.json';
 // The file contents for the current environment will overwrite these during build.
 // The build system defaults to the dev environment which uses `environment.ts`
 // The list of which env maps to which file can be found in `.angular-cli.json`.
-const servicesProxyUrl = 'https://data-intothesky.alpha.grandlyon.com';
-const kongBaseUrl = 'https://kong-dev.alpha.grandlyon.com';
-
 export const environment = {
   version: (<any>packageJson).version,
 
   production: false,
   passwordMinLength: 6,
-
-  backendUrls: {
-    organizations: 'http://localhost:3000/organizations',
-    resources: 'http://localhost:3003',
-    credits: 'http://localhost:3005/credits',
-    auth: 'http://localhost:3002/',
-    middlewareLegacyAuth: 'http://localhost:3004/',
-    email: 'http://localhost:3001/email',
-    matomo: 'https://matomo-intothesky.alpha.grandlyon.com',
-    elasticsearch: `${kongBaseUrl}/es-consumer-aware`,
-  },
-
   enableEsFrontCache: true,
 
   // Path to the built app in a particular language
diff --git a/src/main.ts b/src/main.ts
index 91ec6da5..ac3b2c0a 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -8,5 +8,17 @@ if (environment.production) {
   enableProdMode();
 }
 
-platformBrowserDynamic().bootstrapModule(AppModule)
-  .catch(err => console.log(err));
+fetch('./assets/config/config.json')
+  .then(response => response.json())
+  .then((config) => {
+    if (!config) {
+      return;
+    }
+
+    // Store the response so that your ConfigService can read it.
+    window['portailDataEnvConfig'] = config;
+
+    platformBrowserDynamic().bootstrapModule(AppModule)
+      .catch(err => console.log(err));
+
+  });
-- 
GitLab