diff --git a/.gitignore b/.gitignore index cf70988..13d81d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ **/node_modules +docker/mongodb/data \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 9de7b71..f125b0a 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -4,4 +4,11 @@ services: container_name: "mongo" image: "mongo:latest" ports: - - "27017:27017" \ No newline at end of file + - "27017:27017" + environment: + - "MONGO_INITDB_DATABASE=express-test" + - "MONGO_INITDB_ROOT_USERNAME=god" + - "MONGO_INITDB_ROOT_PASSWORD=P@ssword" + volumes: + - "./mongodb/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d/:ro" + - "./mongodb/data:/data/db" \ No newline at end of file diff --git a/docker/mongodb/docker-entrypoint-initdb.d/initDatabase.js b/docker/mongodb/docker-entrypoint-initdb.d/initDatabase.js new file mode 100644 index 0000000..7aa3d49 --- /dev/null +++ b/docker/mongodb/docker-entrypoint-initdb.d/initDatabase.js @@ -0,0 +1,12 @@ +db.test.insert({id: 'test'}); + +db.createUser( + { + user: "application_user", + pwd: "Password1", + roles: + [ + { role: "readWrite", db: "db_application" } + ] + } +) \ No newline at end of file diff --git a/src/js/controller/applicationCtrl.js b/src/js/controller/applicationCtrl.js index d366b1c..416394d 100644 --- a/src/js/controller/applicationCtrl.js +++ b/src/js/controller/applicationCtrl.js @@ -1,6 +1,8 @@ const Repository = require('../repository/repository'); -const router = require('express').Router(); +const authenticationFilter = require('../filter/authenticationFilter'); +const express = require('express'); +const router = express.Router(); const applicationRepository = new Repository('applications'); router.get('/', (request, response) => { @@ -36,7 +38,7 @@ router.put('/:applicationId', (request, response) => { }); }); -router.delete('/:applicationId', (request, response) => { +router.delete('/:applicationId', authenticationFilter, (request, response) => { const applicationId = request.params.applicationId; applicationRepository.find({_id: applicationId}, entity => { if (entity.length === 0) { diff --git a/src/js/controller/templateCtrl.js b/src/js/controller/templateCtrl.js index 6ea9355..df9e75e 100644 --- a/src/js/controller/templateCtrl.js +++ b/src/js/controller/templateCtrl.js @@ -1,4 +1,3 @@ -const Repository = require('../repository/repository'); const router = require('express').Router(); // Develop routes here diff --git a/src/js/controller/userCtrl.js b/src/js/controller/userCtrl.js index c5cd1c7..9a2dc25 100644 --- a/src/js/controller/userCtrl.js +++ b/src/js/controller/userCtrl.js @@ -8,10 +8,12 @@ router.post('/login', (request, response) => { if (!loginRequest) { response.status(403).send(); } else { - userService.checkCredentials(loginRequest.login, loginRequest.password, () => { - const tokenPayload = { login: loginRequest.login }; - response.json(tokenService.build(tokenPayload)); - }, () => response.status(403).send()); + userService.checkCredentials(loginRequest.login, loginRequest.password, + () => { + const tokenPayload = { login: loginRequest.login }; + response.json(tokenService.build(tokenPayload)); + }, + () => response.status(403).send()); } }); diff --git a/src/js/filter/authenticationFilter.js b/src/js/filter/authenticationFilter.js new file mode 100644 index 0000000..8295da5 --- /dev/null +++ b/src/js/filter/authenticationFilter.js @@ -0,0 +1,17 @@ +const tokenService = require('../service/tokenService'); + +module.exports = (request, response, next) => { + const authenticationHeader = request.headers.authorization; + + if (authenticationHeader) { + const token = authenticationHeader.split(' ')[1]; + + if (tokenService.isValid(token)) { + next(); + } else { + response.status(403).send(); + } + } else { + response.status(401).send(); + } +}; \ No newline at end of file diff --git a/src/js/repository/mongoClient.js b/src/js/repository/mongoClient.js index 2024f2e..2a3bb10 100644 --- a/src/js/repository/mongoClient.js +++ b/src/js/repository/mongoClient.js @@ -2,9 +2,18 @@ const mongodb = require('mongodb'); const configuration = require('../configuration'); const mongoConfig = configuration.mongodb; +function buildDatabaseUrl() { + const username = mongoConfig.username; + const password = encodeURIComponent(mongoConfig.password); + const url = `${mongoConfig.url}:${mongoConfig.port}`; + const test = `mongodb://${username}:${password}@${url}`; + console.log(test); + return test; +} + class MongoClient { constructor() { - mongodb.MongoClient.connect(mongoConfig.url, (error, client) => { + mongodb.MongoClient.connect(buildDatabaseUrl(), (error, client) => { if (error !== null) { throw new Error(`Unable de connect to Mongo database: ${error}`); } @@ -61,6 +70,5 @@ class MongoClient { } } -// Define a singleton of class "MongoClient". -const mongoClient = new MongoClient(); -module.exports = mongoClient; \ No newline at end of file +const singleton = new MongoClient(); +module.exports = singleton; \ No newline at end of file diff --git a/src/js/repository/repository.js b/src/js/repository/repository.js index 44de763..a47d580 100644 --- a/src/js/repository/repository.js +++ b/src/js/repository/repository.js @@ -13,7 +13,7 @@ function convertIdToMongodbFormat(entity) { module.exports = class Repository { /** * Creates a new repository which read and write into the {@code collectionName} collection in database. - * @param {*} collectionName + * @param {String} collectionName */ constructor(collectionName) { this.collectionName = collectionName; @@ -22,8 +22,9 @@ module.exports = class Repository { /** * Returns the entities that matches criteria in {@code query}. - * @param {*} query The query which contains criteria to find some entities. - * @param {*} onSuccess The function to execute after getting entities. + * @param {Object} query The query which contains criteria to find some entities. + * @param {Function} onSuccess The function to execute after getting entities. + * @param {Function} onError The function to execute if entity finding failed. */ find(query, onSuccess, onError) { convertIdToMongodbFormat(query); diff --git a/src/js/service/passwordService.js b/src/js/service/passwordService.js index 397c8ed..3d3c902 100644 --- a/src/js/service/passwordService.js +++ b/src/js/service/passwordService.js @@ -2,11 +2,22 @@ const bcrypt = require('bcrypt'); const saltRounds = 10; class PasswordService { + /** + * Hashes the password in parameters. + * @param {String} password The plain text password. + * @returns The hashed password. + */ hashPassword(password) { const salt = bcrypt.genSaltSync(saltRounds); return bcrypt.hashSync(password, salt); } + /** + * Checks if the {@code plainTextPassword} matches the hashed password. + * @param {String} plainTextPassword The plain text password. + * @param {String} hashedPassword The hashed password. + * @returns A boolean. + */ areSamePasswords(plainTextPassword, hashedPassword) { return bcrypt.compareSync(plainTextPassword, hashedPassword); } diff --git a/src/js/service/tokenService.js b/src/js/service/tokenService.js index 5160ec9..17180d9 100644 --- a/src/js/service/tokenService.js +++ b/src/js/service/tokenService.js @@ -3,10 +3,20 @@ const configuration = require('../configuration'); const securityConfig = configuration.security; class TokenService { + /** + * Builds a JWT token. + * @param {Object} tokenPayload The JWT payload. + * @returns {String} The JWT token. + */ build(tokenPayload) { return jwt.sign(tokenPayload, securityConfig.jwt.secret, {expiresIn: securityConfig.jwt.validity}); } + /** + * Checks if the given token is valid, and provides from this application or not. + * @param {String} token The JWT token to check. + * @returns A boolean. + */ isValid(token) { try { jwt.verify(token, securityConfig.jwt.secret); @@ -17,5 +27,5 @@ class TokenService { } } -const jwtInstance = new TokenService(); -module.exports = jwtInstance; \ No newline at end of file +const singleton = new TokenService(); +module.exports = singleton; \ No newline at end of file diff --git a/src/js/service/userService.js b/src/js/service/userService.js index d8cfdb6..b8c5a95 100644 --- a/src/js/service/userService.js +++ b/src/js/service/userService.js @@ -15,14 +15,7 @@ class UserService { } /** - * - */ - isAuthenticated() { - return false; - } - - /** - * + * Checks if credentials matches to an existing user, that have this password. * @param {String} login User login. * @param {String} password User password, in plain text. * @param {Function} onSuccess Callback function to execute if a user exists with this login. diff --git a/src/mongodb/initDatabase.js b/src/mongodb/initDatabase.js deleted file mode 100644 index 1675e61..0000000 --- a/src/mongodb/initDatabase.js +++ /dev/null @@ -1,14 +0,0 @@ -use express-test; - -db.collection.test.insert({id: 'test'}); - -db.createUser( - { - user: "express-user", - pwd: "P@ssword1", - roles: - [ - { role: "readWrite", db: "express-test" } - ] - } -) \ No newline at end of file diff --git a/src/resources/application.yml b/src/resources/application.yml index ce52fa2..f189a13 100644 --- a/src/resources/application.yml +++ b/src/resources/application.yml @@ -1,8 +1,9 @@ mongodb: - url: 'mongodb://localhost:27017' - username: 'express-user' - password: 'P@ssword1' - database: 'express-test' + url: 'localhost' + port: 27017 + username: 'application_user' + password: 'Password1' + database: 'db_application' security: jwt: secret: 5ubtcCCo7hWBqjNGtzzVKnLT1KxN9uS4D6kRZowCunZAYPmxtKy6mvgoxANe4WqLVfiVI7AZSVqZCtvlSWFwIsnXGH6lxeKG0U8Wu7Kw0jwfFOGLvlO8bXaB