From 3dcecfc0684676f1aa3b10cd12c1fdc683ad6d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Torres?= Date: Tue, 12 Nov 2024 17:29:36 -0600 Subject: [PATCH] Fix the logic of the token JWT and the compilation configuration in production --- api/api-routes.js | 36 ++++++++----- docker-compose.yml | 2 +- dockerfile | 6 +++ .../interceptors/jwtToken.Interceptor.ts | 15 ++++++ frontend/src/app/app.config.ts | 54 ++++++++++--------- frontend/src/environments/environment.ts | 12 ++--- 6 files changed, 78 insertions(+), 47 deletions(-) create mode 100644 frontend/src/app/@core/interceptors/jwtToken.Interceptor.ts diff --git a/api/api-routes.js b/api/api-routes.js index 8d71c43..0d824f5 100644 --- a/api/api-routes.js +++ b/api/api-routes.js @@ -1,8 +1,13 @@ // Filename: api-routes.js // Initialize express router let router = require("express").Router(); +var { expressjwt: jwt } = require("express-jwt"); +const environment = require("./config/environment"); + +const jwtAuth = jwt({ secret: environment.secret, algorithms: ["HS256"] }); + // Set default API response -router.get("/", function(req, res) { +router.get("/", function (req, res) { res.json({ status: "API Its Working", message: "Welcome to RESTHub crafted with love!" @@ -11,35 +16,38 @@ router.get("/", function(req, res) { // Import user controller var userController = require("./controllers/users.controller"); + // user routes router .route("/users") - .get(userController.index) + .get(jwtAuth, userController.index) .post(userController.new); router .route("/user/:user_id") - .get(userController.view) - .patch(userController.update) - .put(userController.update) - .delete(userController.delete); -router.route("/user/authenticate").post(userController.authenticate); + .get(jwtAuth, userController.view) + .patch(jwtAuth, userController.update) + .put(jwtAuth, userController.update) + .delete(jwtAuth, userController.delete); router .route("/user/changepassword/:user_id") - .put(userController.changePassword); + .put(jwtAuth, userController.changePassword); +// Public route for user authentication (without jwtAuth) +router.route("/user/authenticate").post(userController.authenticate); // Import Contact controller var contactController = require("./controllers/contact.controller"); + // Contact routes router .route("/contacts") - .get(contactController.index) - .post(contactController.new); + .get(jwtAuth, contactController.index) + .post(jwtAuth, contactController.new); router .route("/contact/:contact_id") - .get(contactController.view) - .patch(contactController.update) - .put(contactController.update) - .delete(contactController.delete); + .get(jwtAuth, contactController.view) + .patch(jwtAuth, contactController.update) + .put(jwtAuth, contactController.update) + .delete(jwtAuth, contactController.delete); // Export API routes module.exports = router; diff --git a/docker-compose.yml b/docker-compose.yml index bfc8b94..d331143 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: BASE_HREF: ${BASE_HREF:-/} container_name: ${ID_PROJECT:-mean}_angular_express ports: - - "4200:3000" #specify ports forewarding + - "3000:3000" #specify ports forewarding # Below database enviornment variable for api is helpful when you have to use database as managed service environment: - SECRET=Thisismysecret diff --git a/dockerfile b/dockerfile index 59103f8..a5ec716 100644 --- a/dockerfile +++ b/dockerfile @@ -11,6 +11,12 @@ WORKDIR /app COPY /frontend . +## Change apiEndpoint in environment.ts +RUN sh -c "sed -i 's|http://localhost:3000/api|/api|' src/environments/environment.ts" + +## Change production to true in environment.ts +RUN sh -c "sed -i 's|production: false|production: true|' src/environments/environment.ts" + ARG BASE_HREF=/ ## Build the angular app in production mode and store the artifacts in dist folder diff --git a/frontend/src/app/@core/interceptors/jwtToken.Interceptor.ts b/frontend/src/app/@core/interceptors/jwtToken.Interceptor.ts new file mode 100644 index 0000000..a385642 --- /dev/null +++ b/frontend/src/app/@core/interceptors/jwtToken.Interceptor.ts @@ -0,0 +1,15 @@ +import { HttpInterceptorFn } from '@angular/common/http'; + +export const jwtInterceptor: HttpInterceptorFn = (req, next) => { + // Obtén el token del localStorage + const currentUser = JSON.parse(localStorage.getItem('currentUser') || '{}'); + const token = currentUser?.token; + + // Clona la solicitud y agrega el encabezado de autorización si existe el token + const authReq = token + ? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }) + : req; + + // Pasa la solicitud al siguiente manejador + return next(authReq); +}; diff --git a/frontend/src/app/app.config.ts b/frontend/src/app/app.config.ts index 8ad003c..fa24877 100644 --- a/frontend/src/app/app.config.ts +++ b/frontend/src/app/app.config.ts @@ -2,36 +2,38 @@ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideAnimations } from '@angular/platform-browser/animations'; import { provideRouter } from '@angular/router'; -import { provideHttpClient } from '@angular/common/http'; +import { provideHttpClient, withInterceptors } from '@angular/common/http'; import { provideClientHydration } from '@angular/platform-browser'; import { provideToastr } from 'ngx-toastr'; import { routes } from './app.routes'; import { provideErrorTailorConfig } from "./@core/components/validation"; +import { jwtInterceptor } from "./@core/interceptors/jwtToken.Interceptor"; export const appConfig: ApplicationConfig = { - providers: [ - provideHttpClient(), - provideZoneChangeDetection({ eventCoalescing: true }), - provideRouter(routes), - provideClientHydration(), - provideAnimations(), // required animations providers - provideToastr(), // Toastr providers - provideErrorTailorConfig({ - errors: { - useFactory() { - return { - required: 'This field is required', - minlength: ({ requiredLength, actualLength }) => `Expect ${requiredLength} but got ${actualLength}`, - invalidEmailAddress: error => `Email Address is not valid`, - invalidMobile: error => `Invalid Mobile number`, - invalidPassword: error => `Password is weak`, - passwordMustMatch: error => `Password is not matching`, - }; - }, - deps: [] - } - //controlErrorComponent: CustomControlErrorComponent, // Uncomment to see errors being rendered using a custom component - //controlErrorComponentAnchorFn: controlErrorComponentAnchorFn // Uncomment to see errors being positioned differently - }) - ], + providers: [ + provideHttpClient(), + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(routes), + provideClientHydration(), + provideAnimations(), // required animations providers + provideToastr(), // Toastr providers + provideErrorTailorConfig({ + errors: { + useFactory() { + return { + required: 'This field is required', + minlength: ({ requiredLength, actualLength }) => `Expect ${requiredLength} but got ${actualLength}`, + invalidEmailAddress: error => `Email Address is not valid`, + invalidMobile: error => `Invalid Mobile number`, + invalidPassword: error => `Password is weak`, + passwordMustMatch: error => `Password is not matching`, + }; + }, + deps: [] + } + //controlErrorComponent: CustomControlErrorComponent, // Uncomment to see errors being rendered using a custom component + //controlErrorComponentAnchorFn: controlErrorComponentAnchorFn // Uncomment to see errors being positioned differently + }), + provideHttpClient(withInterceptors([jwtInterceptor])), + ], }; diff --git a/frontend/src/environments/environment.ts b/frontend/src/environments/environment.ts index 2996ab6..9561200 100644 --- a/frontend/src/environments/environment.ts +++ b/frontend/src/environments/environment.ts @@ -1,8 +1,8 @@ export const environment = { - production: false, - apiEndpoint: '/api', - angular: 'Angular 18', - bootstrap: 'Bootstrap 5', - expressjs: 'Express.js 4.17.1', - mongoDb : 'MongoDB 7.0', + production: false, + apiEndpoint: 'http://localhost:3000/api', + angular: 'Angular 18', + bootstrap: 'Bootstrap 5', + expressjs: 'Express.js 4.17.1', + mongoDb: 'MongoDB 7.0', };