├── audit ├── auditAction.js └── audit.service.js ├── error ├── error.type.js ├── error.status.js ├── api.error.js └── base.error.js ├── Util ├── generator.js ├── utility.js ├── memory.storage.js ├── validation.js └── jwtUtil.js ├── route ├── export.route.js ├── paypal.route.js ├── upload.route.js ├── user.route.js ├── store.route.js ├── login.route.js ├── noteRoute.js └── book.route.js ├── model ├── store.model.js ├── note.model.js ├── audit.model.js └── book.model.js ├── .env ├── db ├── connection.js ├── pool.js └── queries.js ├── test └── book.test.js ├── error.html ├── success.html ├── README.md ├── services ├── paypal.service.js └── logger.service.js ├── .gitignore ├── payment.html ├── index.html ├── package.json ├── controller ├── upload.controller.js ├── export.controller.js ├── paypal.controller.js ├── store.controller.js ├── noteController.js ├── login.controller.js ├── user.controller.js └── book.controller.js ├── swagger.json ├── scripts └── ddl.sql └── server.js /audit/auditAction.js: -------------------------------------------------------------------------------- 1 | exports.actionList = { 2 | GET_BOOK_LIST: "GET_BOOK_LIST", 3 | GET_USER_LIST: "GET_USER_LIST" 4 | } -------------------------------------------------------------------------------- /error/error.type.js: -------------------------------------------------------------------------------- 1 | var ErrorType = { 2 | API_ERROR : "API_ERROR", 3 | GENERAL_ERROR: "GENERAL_ERROR", 4 | SQL_INJECTION_ERROR : "SQL_INJECTION_ERROR" 5 | 6 | } 7 | 8 | module.exports = ErrorType -------------------------------------------------------------------------------- /Util/generator.js: -------------------------------------------------------------------------------- 1 | var sequential = require("sequential-ids"); 2 | 3 | var generator = new sequential.Generator({ 4 | digits: 3, 5 | restore: "000" 6 | }); 7 | 8 | 9 | generator.start(); 10 | 11 | 12 | module.exports = generator -------------------------------------------------------------------------------- /route/export.route.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | const router = express.Router(); 3 | var exportCtrl = require('../controller/export.controller'); 4 | 5 | router.get("/export/books" , exportCtrl.exportBooks); 6 | module.exports = router -------------------------------------------------------------------------------- /route/paypal.route.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | const router = express.Router(); 3 | var paypalCtrl = require('../controller/paypal.controller'); 4 | 5 | router.get("/buy" , paypalCtrl.createPayment); 6 | 7 | module.exports = router -------------------------------------------------------------------------------- /route/upload.route.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | const router = express.Router(); 3 | var uploadCtrl = require('../controller/upload.controller'); 4 | 5 | router.post("/upload/file" , uploadCtrl.uploadFile); 6 | module.exports = router -------------------------------------------------------------------------------- /error/error.status.js: -------------------------------------------------------------------------------- 1 | var HttpStatusCode = { 2 | OK: 200, 3 | BAD_REQUEST: 400, 4 | NOT_FOUND : 404, 5 | INTERNAL_SERVER_ERROR : 500, 6 | unauthorized: 401, 7 | // AND SO ON 8 | } 9 | 10 | 11 | module.exports = HttpStatusCode -------------------------------------------------------------------------------- /model/store.model.js: -------------------------------------------------------------------------------- 1 | exports.Store = class Store { 2 | 3 | constructor(storeId , StoreName , code , address){ 4 | this.storeId = storeId; 5 | this.StoreName = StoreName; 6 | this.code = code; 7 | this.address = address; 8 | } 9 | } -------------------------------------------------------------------------------- /route/user.route.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | const router = express.Router(); 3 | var userCtrl = require('../controller/user.controller'); 4 | 5 | router.get("/users" , userCtrl.getUserList); 6 | router.post("/users/save" , userCtrl.saveUser); 7 | module.exports = router -------------------------------------------------------------------------------- /route/store.route.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | const router = express.Router(); 3 | var storeCtrl = require('../controller/store.controller'); 4 | 5 | router.get("/stores" , storeCtrl.getStoreList); 6 | router.post("/stores/save" , storeCtrl.saveStore); 7 | 8 | module.exports = router -------------------------------------------------------------------------------- /error/api.error.js: -------------------------------------------------------------------------------- 1 | const BaseError = require("./base.error"); 2 | 3 | class APIError extends BaseError { 4 | constructor(name , httpStatusCode , description , isOperational){ 5 | super(name , httpStatusCode , description , isOperational) 6 | } 7 | } 8 | 9 | module.exports = APIError -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres?currentSchema=bms 2 | PORT=3000 3 | LOG_FILE_PATH=./log 4 | SECRET=epmdjuk9q 5 | UPLOAD_PATH="uploads/" 6 | PAYPAL_CLIENT_ID = *************************************** 7 | PAYPAL_CLIENT_SECRET = *********************************** 8 | PAYPAL_MODE = "sandbox" -------------------------------------------------------------------------------- /model/note.model.js: -------------------------------------------------------------------------------- 1 | exports.Note = class Note { 2 | 3 | constructor(noteId , title , content , createdBy , createdOn){ 4 | this.noteId = noteId; 5 | this.title = title; 6 | this.content = content; 7 | this.createdBy = createdBy; 8 | this.createdOn = createdOn; 9 | } 10 | } -------------------------------------------------------------------------------- /model/audit.model.js: -------------------------------------------------------------------------------- 1 | exports.Audit = class Audit { 2 | 3 | constructor(auditAction , data , status , error , auditBy , auditOn){ 4 | this.auditAction = auditAction; 5 | this.data = data; 6 | this.status = status; 7 | this.error = error; 8 | this.auditBy = auditBy; 9 | this.auditOn = auditOn; 10 | } 11 | } -------------------------------------------------------------------------------- /Util/utility.js: -------------------------------------------------------------------------------- 1 | var randomstring = require("randomstring"); 2 | 3 | 4 | exports.generateStoreCode = () => { 5 | return randomstring.generate({ 6 | length: 5, 7 | charset: 'alphabetic', 8 | capitalization : 'uppercase' 9 | }); 10 | } 11 | 12 | exports.dateFormat = () =>{ 13 | return new Date(Date.now()).toLocaleString(); 14 | } -------------------------------------------------------------------------------- /db/connection.js: -------------------------------------------------------------------------------- 1 | var pool = require('./pool'); 2 | 3 | exports.dbQuery = (queryText, queryParams) => { 4 | return new Promise((resolve , reject) => { 5 | pool.query(queryText, queryParams) 6 | .then(res => { 7 | resolve(res); 8 | }) 9 | .catch(err => { 10 | reject(err); 11 | }) 12 | }); 13 | } -------------------------------------------------------------------------------- /route/login.route.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | const router = express.Router(); 3 | var loginCtrl = require('../controller/login.controller'); 4 | var jwtUtil = require('../Util/jwtUtil'); 5 | 6 | router.get("/login/profile/:userId" , jwtUtil.verifyToken(["admin"]) , loginCtrl.getUserProfile); 7 | router.post("/login/signIn" , loginCtrl.signIn); 8 | module.exports = router -------------------------------------------------------------------------------- /model/book.model.js: -------------------------------------------------------------------------------- 1 | exports.Book = class Book { 2 | 3 | constructor(bookId , title , isbn , description , publisher , author , pages){ 4 | this.bookId = bookId; 5 | this.title = title; 6 | this.isbn = isbn; 7 | this.description = description; 8 | this.publisher = publisher; 9 | this.author = author; 10 | this.pages = pages; 11 | } 12 | } -------------------------------------------------------------------------------- /route/noteRoute.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | const router = express.Router(); 3 | var noteCtrl = require('../controller/noteController'); 4 | 5 | router.get("/notes" , noteCtrl.getAllNotes); 6 | router.post("/notes/save" , noteCtrl.saveNote); 7 | router.put("/notes/update" , noteCtrl.updateNote); 8 | router.delete("/notes/delete/:noteId" , noteCtrl.deleteNote); 9 | 10 | 11 | module.exports = router -------------------------------------------------------------------------------- /route/book.route.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | const router = express.Router(); 3 | var bookCtrl = require('../controller/book.controller'); 4 | 5 | router.get("/books" , bookCtrl.getBookList); 6 | router.get("/books/details/:bookId" , bookCtrl.getBookDetails); 7 | router.post("/books/save" , bookCtrl.saveBook); 8 | router.put("/books/update" , bookCtrl.updateBook); 9 | router.delete("/books/delete/:bookId" , bookCtrl.deleteBook); 10 | 11 | module.exports = router -------------------------------------------------------------------------------- /error/base.error.js: -------------------------------------------------------------------------------- 1 | class BaseError extends Error { 2 | constructor(name , httpStatusCode , description , isOperational){ 3 | super(description); 4 | Object.setPrototypeOf(this , new.target.prototype) 5 | this.name = name; 6 | this.httpStatusCode = httpStatusCode; 7 | this.description = description; 8 | this.isOperational = isOperational; 9 | 10 | Error.captureStackTrace(this); 11 | } 12 | } 13 | 14 | module.exports = BaseError -------------------------------------------------------------------------------- /test/book.test.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | var should =chai.should(); 3 | var expect = chai.expect; 4 | var assert = chai.assert; 5 | 6 | const request = require('supertest'); 7 | const app = require('../server'); 8 | 9 | describe('GET /books', function() { 10 | it('return list of books', function(done) { 11 | request(app) 12 | .get('/api/v1/books') 13 | .expect(200) 14 | .expect((res) =>{ 15 | console.log("book list >>> " + JSON.stringify(res.text)) 16 | }).end(done) 17 | }) 18 | }) -------------------------------------------------------------------------------- /db/pool.js: -------------------------------------------------------------------------------- 1 | const { Pool } = require('pg'); 2 | const dotenv = require('dotenv'); 3 | dotenv.config(); 4 | 5 | const db_config = { 6 | connectionString: process.env.DATABASE_URL, 7 | connectionTimeoutMillis: 300000, 8 | idleTimeoutMillis: 300000, 9 | max: 20, 10 | } 11 | 12 | const pool = new Pool(db_config); 13 | 14 | pool.on('connect', () => { 15 | console.log("database is connect"); 16 | }) 17 | 18 | 19 | pool.on('remove', () => { 20 | console.log("database connection removed"); 21 | }) 22 | 23 | module.exports = pool; -------------------------------------------------------------------------------- /error.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |

Alas :(
10 | An error has occured. 11 |

12 |
13 |
14 |
15 | 16 |
17 |
18 |
19 |
-------------------------------------------------------------------------------- /success.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |

9 | Congratulations !
10 | Successfully completed payment. 11 |

12 |
13 |
14 |
15 | 16 |
17 |
18 |
19 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nodejs-apps 2 | # Notes API & Books API in one application 3 | 4 | Notes-app is an API for listing and creating and updating notes and also an API for listing and details and creating and updating books library 5 | 6 | ## Installation 7 | 8 | Use the package manager npm to install dependencies in package.json 9 | ```bash 10 | npm install 11 | ``` 12 | 13 | ## Usage 14 | 15 | just use node server.js to run the application using the url http://localhost:3000 16 | 17 | ## Contributing 18 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 19 | 20 | Please make sure to update tests as appropriate. 21 | 22 | ## License 23 | [MIT] 24 | -------------------------------------------------------------------------------- /Util/memory.storage.js: -------------------------------------------------------------------------------- 1 | var MemoryStorage = require('memorystorage'); 2 | // here, the MemoryStorage function is available 3 | var store = new MemoryStorage('note-app'); 4 | 5 | 6 | 7 | exports.getKeys = (store) => { 8 | var keys = []; 9 | for (var i=0; i { 17 | var values = []; 18 | for (var i=0; i { 14 | return new Promise( ( resolve , reject ) => { 15 | paypal.payment.create( payment , function( err , payment ) { 16 | if ( err ) { 17 | reject(err); 18 | } 19 | else { 20 | resolve(payment); 21 | } 22 | }); 23 | }); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /dist-server 6 | /tmp 7 | /out-tsc 8 | 9 | # dependencies 10 | /node_modules 11 | package-lock.json 12 | 13 | # IDEs and editors 14 | /.idea 15 | .project 16 | .classpath 17 | .c9/ 18 | *.launch 19 | .settings/ 20 | *.sublime-workspace 21 | 22 | # IDE - VSCode 23 | .vscode/* 24 | !.vscode/settings.json 25 | !.vscode/tasks.json 26 | !.vscode/launch.json 27 | !.vscode/extensions.json 28 | 29 | # misc 30 | /.sass-cache 31 | /connect.lock 32 | /coverage 33 | /libpeerconnection.log 34 | npm-debug.log 35 | yarn-error.log 36 | testem.log 37 | /typings 38 | 39 | # e2e 40 | /e2e/*.js 41 | /e2e/*.map 42 | 43 | # System Files 44 | .DS_Store 45 | Thumbs.db 46 | -------------------------------------------------------------------------------- /payment.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |

An introduction to mean stack

9 |
10 | Description: Start learning mean stack today with this book that is optimized 11 | for experiential learning. 12 |
13 |

Only for $$ 39.00

14 |
15 | 16 | 17 | 18 |
19 |
20 | 21 |
22 |
23 |
24 |
-------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Socket.io 6 | 7 | 8 |

News Feed

9 |
10 | 11 | 12 | 27 | 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "note-app", 3 | "version": "1.0.0", 4 | "description": "note app api", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "mocha --timeout 10000 " 8 | }, 9 | "keywords": [ 10 | "not", 11 | "app" 12 | ], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "babel-polyfill": "^6.26.0", 17 | "bcryptjs": "^2.4.3", 18 | "body-parser": "^1.19.0", 19 | "chai": "^4.3.3", 20 | "cors": "^2.8.5", 21 | "dotenv": "^8.2.0", 22 | "express": "^4.17.1", 23 | "fast-csv": "^4.3.6", 24 | "jsonwebtoken": "^8.5.1", 25 | "memorystorage": "^0.12.0", 26 | "multer": "^1.4.2", 27 | "password-validator": "^5.1.1", 28 | "paypal-rest-sdk": "^1.8.1", 29 | "pg": "^8.5.1", 30 | "randomstring": "^1.1.5", 31 | "sequential-ids": "0.0.0", 32 | "socket.io": "^4.1.2", 33 | "swagger-ui-express": "^4.1.6", 34 | "winston": "^3.3.3" 35 | }, 36 | "devDependencies": { 37 | "supertest": "^6.1.3" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /audit/audit.service.js: -------------------------------------------------------------------------------- 1 | var events = require('events'); 2 | var audit = require('../model/audit.model'); 3 | var queries = require('../db/queries'); 4 | var dbConnection = require('../db/connection'); 5 | 6 | var emitter = new events.EventEmitter(); 7 | 8 | const auditEvent = 'audit'; 9 | emitter.on(auditEvent , function(audit){ 10 | // steps of actions - save into db 11 | console.log("Audit Event Emitter - Audit : " + JSON.stringify(audit)); 12 | try { 13 | values =[audit.auditAction , JSON.stringify(audit.data) , audit.status , audit.error , audit.auditBy , audit.auditOn]; 14 | var auditQuery = queries.queryList.AUDIT_QUERY; 15 | dbConnection.dbQuery(auditQuery , values); 16 | 17 | } catch (error) { 18 | console.log("Audit Event Emitter - error : " + error); 19 | } 20 | 21 | 22 | 23 | 24 | 25 | 26 | }); 27 | 28 | exports.prepareAudit = function(auditAction , data , error , auditBy , auditOn){ 29 | let status = 200; 30 | if(error) 31 | status = 500; 32 | 33 | var auditObj = new audit.Audit(auditAction , data , status , error , auditBy , auditOn) 34 | emitter.emit(auditEvent , auditObj); 35 | } -------------------------------------------------------------------------------- /controller/upload.controller.js: -------------------------------------------------------------------------------- 1 | var util = require('../Util/utility'); 2 | var validationUtil = require('../Util/validation'); 3 | var Logger = require('../services/logger.service'); 4 | var multer = require('multer'); 5 | const logger = new Logger('upload.controller'); 6 | 7 | exports.uploadFile = async (req , res) => { 8 | var auditOn = util.dateFormat(); 9 | try { 10 | var upload = multer({ dest: process.env.UPLOAD_PATH }).single('photo'); 11 | upload(req , res , next => { 12 | 13 | try { 14 | var path= req.file.path; 15 | var file =req.file; 16 | console.log("Path : " + path); 17 | console.log("file : " + JSON.stringify(file)); 18 | // save file in directory 19 | // save meta dat in data base [file name (rename) , size , mimiType , path] 20 | return res.status(200).send({data : 'file is uploaded Successfully '}); 21 | } catch (e) { 22 | throw e; 23 | } 24 | 25 | }); 26 | 27 | } catch (err) { 28 | console.log("Error : " + err); 29 | return res.status(500).send({error : 'Failed to upload file'}); 30 | } 31 | } -------------------------------------------------------------------------------- /Util/validation.js: -------------------------------------------------------------------------------- 1 | var passwordValidator = require('password-validator'); 2 | var passwordChecker = new passwordValidator(); 3 | var bcrypt = require('bcryptjs'); 4 | 5 | exports.isValidEmail = (email) => { 6 | const regEx = /\S+@\S+\.\S+/; 7 | return regEx.test(email); 8 | }; 9 | 10 | exports.isValidatePassword = (password) => { 11 | if (password.length < 8 || password === '') { 12 | return false; 13 | } 14 | return true; 15 | }; 16 | 17 | exports.comparePassword = (password , hashedPassword) =>{ 18 | return bcrypt.compareSync(password , hashedPassword); 19 | } 20 | 21 | 22 | exports.isValidPassword = (password)=>{ 23 | passwordChecker 24 | .is().min(8) // Minimum length 8 25 | .is().max(15) // Maximum length 100 26 | .has().uppercase() // Must have uppercase letters 27 | .has().lowercase() // Must have lowercase letters 28 | .has().digits(2) // Must have at least 2 digits 29 | .has().not().spaces() // Should not have spaces 30 | .is().not().oneOf(['Passw0rd', 'Password123']); // Blacklist these values 31 | 32 | return passwordChecker.validate(password); 33 | } -------------------------------------------------------------------------------- /controller/export.controller.js: -------------------------------------------------------------------------------- 1 | var queries = require('../db/queries'); 2 | var dbConnection = require('../db/connection'); 3 | var util = require('../Util/utility'); 4 | var validationUtil = require('../Util/validation'); 5 | var Logger = require('../services/logger.service'); 6 | var auditService = require('../audit/audit.service'); 7 | var auditAction = require('../audit/auditAction'); 8 | var fastCsv = require('fast-csv'); 9 | var fs = require('fs'); 10 | const ws = fs.createWriteStream("books.csv"); 11 | 12 | const logger = new Logger('export.controller'); 13 | 14 | exports.exportBooks = async (req , res) => { 15 | try { 16 | var bookListQuery = queries.queryList.GET_BOOK_LIST_QUERY; 17 | var result = await dbConnection.dbQuery(bookListQuery); 18 | logger.info("return Book List" , result.rows); 19 | const data = JSON.parse(JSON.stringify(result.rows)); 20 | fastCsv.write(data , {headers : true}).on("end", ()=>{ 21 | console.log("write to books.csv successfully"); 22 | res.download("books.csv" , function(){ 23 | console.log("file downloaded successfully"); 24 | }) 25 | }).pipe(ws); 26 | // return res.status(200).send({data : "export data successfully"}) 27 | } catch (err) { 28 | console.log("Error : " + err); 29 | return res.status(500).send({error : 'Failed to export books'}); 30 | } 31 | } -------------------------------------------------------------------------------- /controller/paypal.controller.js: -------------------------------------------------------------------------------- 1 | var paypalService = require('../services/paypal.service'); 2 | 3 | 4 | exports.createPayment = (req , res) => { 5 | 6 | // create payment object 7 | var payment = { 8 | "intent": "authorize", 9 | "payer": { 10 | "payment_method": "paypal" 11 | }, 12 | "redirect_urls": { 13 | "return_url": "http://127.0.0.1:4000/success", 14 | "cancel_url": "http://127.0.0.1:4000/err" 15 | }, 16 | "transactions": [{ 17 | "amount": { 18 | "total": 39.00, 19 | "currency": "USD" 20 | }, 21 | "description": " a book on mean stack " 22 | }] 23 | } 24 | 25 | paypalService.createPaypalPayment(payment).then((transaction)=>{ 26 | console.log("Create Payment Response"); 27 | console.log("transaction : " + JSON.stringify(transaction)); 28 | var transactionId = transaction.id; 29 | console.log("id : " + transactionId); 30 | // NEED TO LOG ALL TRANSACTION FOR EACH REQUEST AND RESPONSE FOR AUDITING 31 | // generate transaction reference number tx_randomnumber 32 | // transaction status [Success , failed , cancelled , pending] 33 | res.redirect("/success") 34 | }) 35 | .catch((err)=>{ 36 | console.log( err ); 37 | res.redirect("/err") 38 | throw error; 39 | }) 40 | } -------------------------------------------------------------------------------- /controller/store.controller.js: -------------------------------------------------------------------------------- 1 | var queries = require('../db/queries'); 2 | var dbConnection = require('../db/connection'); 3 | var util = require('../Util/utility'); 4 | 5 | exports.getStoreList = async (req , res) => { 6 | try { 7 | var storeListQuery = queries.queryList.GET_STORE_LIST_QUERY; 8 | var result = await dbConnection.dbQuery(storeListQuery); 9 | return res.status(200).send(JSON.stringify(result.rows)); 10 | } catch (err) { 11 | console.log("Error : " + err); 12 | return res.status(500).send({error : 'Failed to list store'}); 13 | } 14 | 15 | } 16 | 17 | 18 | exports.saveStore = async (req , res) => { 19 | 20 | try { 21 | 22 | var createdBy = "admin"; 23 | var createdOn = new Date(); 24 | // req.body 25 | var storeName = req.body.storeName; 26 | var address = req.body.address; 27 | console.log("storeName : " + storeName + " ----- address : " + address) 28 | if(!storeName || !address){ 29 | return res.status(500).send({ error: 'store name and address are required , can not empty' }) 30 | } 31 | 32 | let storeCode= util.generateStoreCode(); 33 | 34 | values =[storeName , storeCode , address , createdBy , createdOn]; 35 | var saveStoreQuery = queries.queryList.SAVE_STORE_QUERY; 36 | await dbConnection.dbQuery(saveStoreQuery , values); 37 | return res.status(201).send("Successfully store created "); 38 | } catch (err) { 39 | console.log("Error : " + err); 40 | return res.status(500).send({error : 'Failed to save store'}); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /services/logger.service.js: -------------------------------------------------------------------------------- 1 | const winston = require('winston'); 2 | const dotenv = require('dotenv'); 3 | dotenv.config(); 4 | 5 | // date + logger level + message 6 | 7 | const dateFormat = () =>{ 8 | return new Date(Date.now()).toLocaleString(); 9 | } 10 | 11 | class LoggerService { 12 | 13 | constructor(route){ 14 | this.route = route; 15 | const logger = winston.createLogger({ 16 | level: 'info', 17 | format: winston.format.printf(info =>{ 18 | let message = `${dateFormat()} | ${info.level.toUpperCase()} | ${info.message} | `; 19 | message = info.obj ? message + `data ${JSON.stringify(info.obj)} | ` : message; 20 | return message; 21 | }), 22 | transports: [ 23 | new winston.transports.Console(), 24 | new winston.transports.File({ filename: `${process.env.LOG_FILE_PATH} / ${route}.log` }), 25 | ], 26 | }); 27 | this.logger = logger; 28 | } 29 | 30 | async info (message){ 31 | this.logger.log('info' , message); 32 | } 33 | 34 | async info (message , obj){ 35 | this.logger.log('info' , message , {obj}); 36 | } 37 | 38 | async error (message){ 39 | this.logger.log('error' , message); 40 | } 41 | 42 | async error (message , obj){ 43 | this.logger.log('error' , message , {obj}); 44 | } 45 | 46 | async debug (message){ 47 | this.logger.log('debug' , message); 48 | } 49 | 50 | async debug (message , obj){ 51 | this.logger.log('debug' , message , {obj}); 52 | } 53 | } 54 | 55 | module.exports = LoggerService; -------------------------------------------------------------------------------- /db/queries.js: -------------------------------------------------------------------------------- 1 | exports.queryList = { 2 | 3 | GET_STORE_LIST_QUERY : 'SELECT STORE_ID, STORE_NAME, STORE_CODE FROM BMS.STORE' , 4 | 5 | SAVE_STORE_QUERY : 'INSERT INTO BMS.STORE (STORE_NAME, STORE_CODE, ADDRESS , CREATED_BY , CREATED_ON) VALUES($1, $2, $3, $4, $5)', 6 | 7 | GET_BOOK_LIST_QUERY : 'SELECT BOOK_ID, BOOK_TITLE, BOOK_AUTHOR, BOOK_PUBLISHER FROM BMS.BOOK', 8 | 9 | GET_BOOK_DETAILS_QUERY : `SELECT BOOK_ID, BOOK_TITLE, BOOK_DESCRIPTION, BOOK_AUTHOR, BOOK_PUBLISHER, BOOK_PAGES 10 | , BOOK.STORE_CODE, store.store_name , store.address FROM BMS.BOOK INNER JOIN BMS.STORE ON BOOK.STORE_CODE = STORE.STORE_CODE 11 | WHERE BOOK_ID =$1`, 12 | 13 | SAVE_BOOK_QUERY : ` INSERT INTO BMS.BOOK (BOOK_TITLE, BOOK_DESCRIPTION, BOOK_AUTHOR, BOOK_PUBLISHER, BOOK_PAGES, STORE_CODE, CREATED_BY , CREATED_ON) 14 | VALUES($1, $2, $3, $4, $5 , $6 , $7 , $8) `, 15 | 16 | UPDATE_BOOK_QUERY : ` 17 | UPDATE BMS.BOOK SET BOOK_TITLE=$1, BOOK_DESCRIPTION=$2, BOOK_AUTHOR=$3, BOOK_PUBLISHER=$4, 18 | BOOK_PAGES=$5, STORE_CODE=$6, CREATED_BY=$7 , CREATED_ON=$8 19 | WHERE BOOK_ID=$9 20 | `, 21 | 22 | DELETE_BOOK_QUERY : ` DELETE FROM BMS.BOOK WHERE BOOK_ID=$1 `, 23 | 24 | AUDIT_QUERY : `INSERT INTO BMS.APP_AUDIT (AUDIT_ACTION, AUDIT_DATA, AUDIT_STATUS, AUDIT_ERROR , AUDIT_BY, AUDIT_ON) VALUES($1, $2, $3, $4, $5, $6) 25 | `, 26 | 27 | GET_USER_LIST_QUERY : ` SELECT USER_ID, USERNAME, EMAIL, USER_TYPE_CODE, FULL_NAME, ACTIVE FROM BMS.APP_USER `, 28 | 29 | IS_USER_EXISTS_QUERY : ` SELECT COUNT(USER_ID) FROM BMS.APP_USER WHERE LOWER(USERNAME) =LOWER($1) OR LOWER(EMAIL)=LOWER($2) `, 30 | 31 | SAVE_USER_QUERY : ` INSERT INTO BMS.APP_USER (USERNAME, PASSWORD, EMAIL, USER_TYPE_CODE, FULL_NAME, CREATED_ON, CREATED_BY) VALUES($1, $2, $3, $4, $5, $6, $7) returning * `, 32 | 33 | LOGIN_QUERY : ` SELECT USER_ID, USERNAME, PASSWORD , EMAIL, USER_TYPE_CODE, FULL_NAME, ACTIVE FROM BMS.APP_USER WHERE LOWER(USERNAME) = LOWER($1) AND ACTIVE = 1 `, 34 | 35 | 36 | 37 | 38 | 39 | } -------------------------------------------------------------------------------- /Util/jwtUtil.js: -------------------------------------------------------------------------------- 1 | var jwt = require('jsonwebtoken'); 2 | const dotenv = require('dotenv'); 3 | dotenv.config(); 4 | 5 | exports.generateToken = (userId , username , email , fullname , userRoles , userTypeCode)=>{ 6 | var token = jwt.sign({ 7 | userId:userId, 8 | username:username, 9 | email: email, 10 | fullname:fullname, 11 | roles:userRoles, 12 | userType : userTypeCode, 13 | } , process.env.SECRET , {expiresIn :"3d"}) 14 | return token; 15 | } 16 | 17 | exports.verifyToken = function(roles){ 18 | return async (req, res, next) => { 19 | try { 20 | const {token} = req.headers; 21 | console.log("token : " + token) 22 | if(!token){ 23 | console.log("No token exist"); 24 | return res.status(500).send({error : 'Token is not exist'}) 25 | } 26 | // should validate if loggedIn user has the same role 27 | var decode = jwt.verify(token , process.env.SECRET); 28 | console.log("decode:" + JSON.stringify(decode)) 29 | req.user = { 30 | userId:decode.userId, 31 | username:decode.username, 32 | email: decode.email, 33 | fullname:decode.fullname, 34 | roles:decode.roles, 35 | userType : roles.userType 36 | } 37 | console.log("roles : " + roles); 38 | 39 | if(!this.hasRole(roles , decode.roles)){ 40 | console.log("Error : not have the same role"); 41 | return res.status(401).send({error : 'Authentication failed'}) 42 | } 43 | console.log("valid token"); 44 | next(); 45 | } catch (error) { 46 | next(error); 47 | } 48 | 49 | } 50 | } 51 | 52 | exports.hasRole = function(routeRoles , userRoles){ 53 | console.log("routeRoles : " + routeRoles) 54 | let result= false; 55 | userRoles.forEach(role => { 56 | if(routeRoles.includes(role)){ 57 | result = true; 58 | return; 59 | } 60 | }); 61 | console.log("result : " + result); 62 | return result; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "1.0.0", 5 | "title": "Note & Books API", 6 | "description": "Note & Books API", 7 | "license": { 8 | "name": "MIT", 9 | "url": "https://opensource.org/licenses/MIT" 10 | } 11 | }, 12 | "host": "localhost:3000", 13 | "basePath": "/", 14 | "tags": [ 15 | { 16 | "name": "Note & Books", 17 | "description": "API" 18 | } 19 | ], 20 | "schemes": [ 21 | "http" 22 | ], 23 | "consumes": [ 24 | "application/json" 25 | ], 26 | "produces": [ 27 | "application/json" 28 | ], 29 | "paths": { 30 | "/api/v1/books": { 31 | "get": { 32 | "description": "Returns all BOOKS from the system that the user has access to", 33 | "produces": [ 34 | "application/json" 35 | ], 36 | "responses": { 37 | "200": { 38 | "description": "A list of books.", 39 | "schema": { 40 | "type": "array", 41 | "items": { 42 | "$ref": "#/definitions/books" 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | }, 50 | "definitions":{ 51 | "book":{ 52 | "required":[ 53 | "title", 54 | "isbn", 55 | "publisher", 56 | "author" 57 | ], 58 | "properties":{ 59 | "bookId":{ 60 | "type":"integer" 61 | }, 62 | "title":{ 63 | "type":"string" 64 | }, 65 | "isbn":{ 66 | "type":"string" 67 | }, 68 | "description":{ 69 | "type":"string" 70 | }, 71 | "publisher":{ 72 | "type":"string" 73 | }, 74 | "author":{ 75 | "type":"string" 76 | }, 77 | "pages":{ 78 | "type":"integer" 79 | } 80 | } 81 | }, 82 | "books":{ 83 | "$ref": "#/definitions/book" 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /controller/noteController.js: -------------------------------------------------------------------------------- 1 | var generator = require('../Util/generator'); 2 | var memStorage = require('../Util/memory.storage'); 3 | var model = require('../model/note.model'); 4 | 5 | 6 | exports.getAllNotes = (req , res) => { 7 | // var seqId = generator.generate(); 8 | // memStorage.store.setItem(seqId , "1st_key"); 9 | // var seqId_2 = generator.generate(); 10 | // memStorage.store.setItem(seqId_2 , "2nd_key"); 11 | 12 | // var keys = memStorage.getKeys(memStorage.store); 13 | var values = memStorage.getValues(memStorage.store); 14 | console.log("Values ....... " + JSON.stringify(values)); 15 | return res.status(200).send(JSON.stringify(values)); 16 | } 17 | 18 | exports.saveNote = (req , res) => { 19 | var seqId = generator.generate(); 20 | var createdBy = "admin"; 21 | var createdOn = new Date(); 22 | // req.body 23 | var title = req.body.title; 24 | var content = req.body.content; 25 | if(!title || !content){ 26 | return res.status(500).send({ error: 'Title and Content should not be empty' }) 27 | } 28 | 29 | var Note = model.Note; 30 | var noteObj = new Note(seqId , title , content , createdBy , createdOn); 31 | memStorage.store.setItem(seqId , noteObj); 32 | return res.status(201).send("Successfully note saved "); 33 | } 34 | 35 | 36 | exports.updateNote = (req , res) => { 37 | 38 | var createdBy = "admin"; 39 | var createdOn = new Date(); 40 | // req.body 41 | var noteId = req.body.noteId; 42 | var title = req.body.title; 43 | var content = req.body.content; 44 | if(!noteId){ 45 | return res.status(500).send({ error: 'noteId should not be empty' }) 46 | } 47 | if(!title || !content){ 48 | return res.status(500).send({ error: 'Title and Content should not be empty' }) 49 | } 50 | 51 | var noteItem = memStorage.store.getItem(noteId); 52 | if(!noteItem){ 53 | return res.status(500).send({ error: 'noteId is not exist' }) 54 | } 55 | 56 | var Note = model.Note; 57 | var noteObj = new Note(noteId , title , content , createdBy , createdOn); 58 | memStorage.store.setItem(noteId , noteObj); 59 | return res.status(200).send("Successfully note updated "); 60 | } 61 | 62 | 63 | exports.deleteNote = (req , res) => { 64 | var noteId = req.params.noteId; 65 | 66 | // validate not empty 67 | if(!noteId){ 68 | return res.status(500).send({ error: 'can not delete empty noteId' }) 69 | } 70 | 71 | // validate is already exists 72 | var noteItem = memStorage.store.getItem(noteId); 73 | if(!noteItem){ 74 | return res.status(500).send({ error: 'noteId is not exist' }) 75 | } 76 | 77 | // is exits 78 | memStorage.store.removeItem(noteId); 79 | return res.status(200).send("Successfully note deleted "); 80 | } 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /scripts/ddl.sql: -------------------------------------------------------------------------------- 1 | CREATE SCHEMA bms; 2 | 3 | -- bms.book definition 4 | 5 | -- Drop table 6 | 7 | -- DROP TABLE bms.book; 8 | 9 | CREATE TABLE bms.book ( 10 | book_id serial NOT NULL, 11 | book_title varchar(300) NOT NULL, 12 | book_description varchar(1000) NULL, 13 | book_author varchar(50) NOT NULL, 14 | book_publisher varchar(50) NOT NULL, 15 | book_pages int4 NULL, 16 | store_code varchar(5) NOT NULL, 17 | created_on timestamp NOT NULL, 18 | created_by varchar(50) NOT NULL, 19 | CONSTRAINT book_pkey PRIMARY KEY (book_id) 20 | ); 21 | 22 | 23 | -- bms.store definition 24 | 25 | -- Drop table 26 | 27 | -- DROP TABLE bms.store; 28 | 29 | CREATE TABLE bms.store ( 30 | store_id serial NOT NULL, 31 | store_name varchar(100) NOT NULL, 32 | store_code varchar(5) NOT NULL, 33 | created_on timestamp NOT NULL, 34 | created_by varchar(50) NOT NULL, 35 | address varchar(200) NOT NULL, 36 | CONSTRAINT store_pkey PRIMARY KEY (store_id) 37 | ); 38 | 39 | -- app_audit 40 | CREATE TABLE bms.app_audit ( 41 | audit_id serial NOT NULL, 42 | audit_action varchar(100) NOT NULL, 43 | audit_data json NULL, 44 | audit_by varchar(50) NOT NULL, 45 | audit_on timestamp NOT NULL, 46 | audit_status varchar(50) NULL, 47 | audit_error json NULL, 48 | CONSTRAINT app_audit_pkey PRIMARY KEY (audit_id) 49 | ); 50 | 51 | CREATE TABLE bms.app_user ( 52 | user_id serial NOT NULL, 53 | username varchar(100) NOT NULL, 54 | "password" varchar(100) NOT NULL, 55 | email varchar(355) NOT NULL, 56 | user_type_code varchar(10) NOT NULL, 57 | full_name varchar(500) NOT NULL, 58 | active int2 NULL DEFAULT 1, 59 | created_on timestamp NULL, 60 | created_by varchar(100) NULL, 61 | updated_on timestamp NULL, 62 | updated_by varchar(100) NULL, 63 | CONSTRAINT user_email_key UNIQUE (email), 64 | CONSTRAINT user_pkey PRIMARY KEY (user_id), 65 | CONSTRAINT user_username_key UNIQUE (username) 66 | ); 67 | 68 | CREATE TABLE bms.app_group ( 69 | group_id serial NOT NULL, 70 | group_name varchar(100) NOT NULL, 71 | CONSTRAINT group_group_name_key UNIQUE (group_name), 72 | CONSTRAINT group_pkey PRIMARY KEY (group_id) 73 | ); 74 | 75 | CREATE TABLE bms.app_role ( 76 | role_id serial NOT NULL, 77 | role_name varchar(100) NOT NULL, 78 | CONSTRAINT role_pkey PRIMARY KEY (role_id), 79 | CONSTRAINT role_role_name_key UNIQUE (role_name) 80 | ); 81 | 82 | CREATE TABLE bms.user_group ( 83 | user_group_id serial NOT NULL, 84 | user_id int4 NULL, 85 | group_id int4 NULL, 86 | CONSTRAINT user_group_pkey PRIMARY KEY (user_group_id) 87 | ); 88 | 89 | CREATE TABLE bms.group_role ( 90 | group_role_id serial NOT NULL, 91 | group_id int4 NULL, 92 | role_id int4 null, 93 | CONSTRAINT group_role_pkey PRIMARY KEY (group_role_id) 94 | ); 95 | 96 | CREATE TABLE bms.user_type ( 97 | user_type_id serial NOT NULL, 98 | user_type_name varchar(500) NOT NULL, 99 | user_type_code varchar(10) NOT NULL, 100 | CONSTRAINT user_type_pkey PRIMARY KEY (user_type_id) 101 | ); -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | // setup server 2 | var express = require('express'); 3 | var cors = require('cors'); 4 | var bodyParser = require('body-parser'); 5 | var noteRoute = require('./route/noteRoute'); 6 | var storeRoute = require('./route/store.route'); 7 | var bookRoute = require('./route/book.route'); 8 | var userRoute = require('./route/user.route'); 9 | var loginRoute = require('./route/login.route'); 10 | var uploadRoute = require('./route/upload.route'); 11 | var exportRoute = require('./route/export.route'); 12 | var paypalRoute = require('./route/paypal.route'); 13 | const swaggerUi = require('swagger-ui-express'); 14 | const swaggerDocument = require('./swagger.json'); 15 | 16 | var app = express(); 17 | const { Server } = require("socket.io"); 18 | 19 | 20 | app.use(cors()) 21 | 22 | // parse application/x-www-form-urlencoded 23 | app.use(bodyParser.urlencoded({ extended: false })) 24 | 25 | // parse application/json 26 | app.use(bodyParser.json()); 27 | 28 | app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); 29 | 30 | // Expose the node_modules folder as static resources (to access socket.io.js in the browser) 31 | app.use('/static', express.static('node_modules')); 32 | 33 | app.get("/" , function(req , res) { 34 | // res.send("Server started ........"); 35 | res.sendFile(__dirname + '/index.html') 36 | }); 37 | 38 | app.get("/payment" , function(req , res) { 39 | // res.send("Server started ........"); 40 | res.sendFile(__dirname + '/payment.html') 41 | }); 42 | 43 | // success page 44 | app.get('/success' , (req ,res ) => { 45 | res.sendFile(__dirname + '/success.html') 46 | }) 47 | // error page 48 | app.get('/err' , (req , res) => { 49 | res.sendFile(__dirname + '/error.html') 50 | }) 51 | 52 | app.use("/api/v1" , noteRoute); 53 | app.use("/api/v1" , storeRoute); 54 | app.use("/api/v1" , bookRoute); 55 | app.use("/api/v1" , userRoute); 56 | app.use("/api/v1" , loginRoute); 57 | app.use("/api/v1" , uploadRoute); 58 | app.use("/api/v1" , exportRoute); 59 | app.use("/api/v1" , paypalRoute); 60 | 61 | 62 | 63 | const server= app.listen(4000, () => { 64 | console.log(`Server start ....... `) 65 | }) 66 | 67 | // initialize & listen to server 68 | const io = new Server(server); 69 | // Handle connection 70 | io.on('connection', function (socket) { 71 | console.log("Connected successfully to the socket ..."); 72 | 73 | setInterval(function(){ 74 | var news = getNews(); 75 | // Send news on the socket 76 | socket.emit('news', news); 77 | } , 5000); 78 | 79 | 80 | socket.on('my other event', function (data) { 81 | console.log(data); 82 | }); 83 | }); 84 | 85 | function getNews(){ 86 | var length = Math.floor(Math.random() * 21); 87 | var news = []; 88 | for(var i = 0; i < length ; i++ ){ 89 | var val = {id : i , title : 'The cure of the Sadness is to play Videogames' + i , date: new Date() } 90 | news.push(val); 91 | } 92 | return news 93 | } 94 | 95 | 96 | 97 | 98 | 99 | module.exports = app -------------------------------------------------------------------------------- /controller/login.controller.js: -------------------------------------------------------------------------------- 1 | var queries = require('../db/queries'); 2 | var dbConnection = require('../db/connection'); 3 | var util = require('../Util/utility'); 4 | var validationUtil = require('../Util/validation'); 5 | var Logger = require('../services/logger.service'); 6 | var auditService = require('../audit/audit.service'); 7 | var auditAction = require('../audit/auditAction'); 8 | var APIError = require('../error/api.error'); 9 | var errorStatus = require('../error/error.status'); 10 | var errorType = require('../error/error.type'); 11 | var bcrypt = require('bcryptjs'); 12 | var jwtUtil = require('../Util/jwtUtil'); 13 | 14 | const logger = new Logger('login.controller'); 15 | 16 | 17 | exports.getUserProfile = async (req , res) => { 18 | var user = req.user; 19 | try { 20 | return res.status(200).send(JSON.stringify(user)); 21 | } catch (err) { 22 | console.log("Error : " + err); 23 | let errorMessage = 'Failed to get user : ' + err; 24 | return res.status(500).send({error : 'Failed to get user'}); 25 | } 26 | } 27 | 28 | exports.signIn = async (req , res) => { 29 | try { 30 | const {username , password} = req.body; 31 | 32 | /** 33 | * 1- validate is not empty 34 | * 2- get user by username 35 | * 3- Compare password 36 | * 4- get user roles 37 | * 5- generate token 38 | */ 39 | 40 | if(!username || !password){ 41 | return res.status(500).send({ error: 'username , password are required , can not empty' }) 42 | } 43 | 44 | var loginQuery = queries.queryList.LOGIN_QUERY; 45 | var result = await dbConnection.dbQuery(loginQuery , [username]); 46 | var dbResponse = result.rows[0]; 47 | if(dbResponse == null){ 48 | logger.info("user : ["+username+"] not exists in db"); 49 | return res.status(errorStatus.unauthorized).send({ error: 'Invalid username or password' }); 50 | } 51 | 52 | var isPasswordValid = validationUtil.comparePassword(password , dbResponse.password); 53 | if(!isPasswordValid){ 54 | logger.info("Invalid password"); 55 | return res.status(errorStatus.unauthorized).send({ error: 'Invalid username or password' }); 56 | } 57 | 58 | var userRoles = await this.getUserRoles(dbResponse.user_id , req , res); 59 | console.log("userRoles : " + JSON.stringify(userRoles)); 60 | var token = jwtUtil.generateToken(dbResponse.user_id , dbResponse.username , dbResponse.email , dbResponse.FULL_NAME , userRoles , dbResponse.user_type_code); 61 | return res.status(200).send(JSON.stringify(token)); 62 | } catch (err) { 63 | logger.error("Failed to SignIn , Invalid username or password" + JSON.stringify(err)) 64 | return res.status(500).send({error : 'Failed to SignIn , Invalid username or password'}); 65 | } 66 | 67 | } 68 | 69 | 70 | exports.getUserRoles = async (userId) => { 71 | try { 72 | let roles = ["user"]; 73 | return roles; 74 | } catch (err) { 75 | 76 | } 77 | 78 | } 79 | 80 | 81 | -------------------------------------------------------------------------------- /controller/user.controller.js: -------------------------------------------------------------------------------- 1 | var queries = require('../db/queries'); 2 | var dbConnection = require('../db/connection'); 3 | var util = require('../Util/utility'); 4 | var validationUtil = require('../Util/validation'); 5 | var Logger = require('../services/logger.service'); 6 | var auditService = require('../audit/audit.service'); 7 | var auditAction = require('../audit/auditAction'); 8 | var APIError = require('../error/api.error'); 9 | var errorStatus = require('../error/error.status'); 10 | var errorType = require('../error/error.type'); 11 | var bcrypt = require('bcryptjs'); 12 | 13 | const logger = new Logger('user.controller'); 14 | 15 | exports.getUserList = async (req , res) => { 16 | var auditOn = util.dateFormat(); 17 | try { 18 | var userListQuery = queries.queryList.GET_USER_LIST_QUERY; 19 | var result = await dbConnection.dbQuery(userListQuery); 20 | logger.info("return user List" , result.rows); 21 | auditService.prepareAudit(auditAction.actionList.GET_USER_LIST , result.rows , null , "postman" , auditOn); 22 | return res.status(200).send(JSON.stringify(result.rows)); 23 | } catch (err) { 24 | console.log("Error : " + err); 25 | let errorMessage = 'Failed to get users : ' + err; 26 | auditService.prepareAudit(auditAction.actionList.GET_USER_LIST , null , JSON.stringify(errorMessage) , "postman" , auditOn); 27 | return res.status(500).send({error : 'Failed to get users'}); 28 | } 29 | } 30 | 31 | /** 32 | 33 | * @param {*} req 34 | * @param {*} res 35 | * @returns 36 | */ 37 | exports.saveUser = async (req , res) => { 38 | 39 | try { 40 | 41 | var createdBy = "admin"; 42 | var createdOn = new Date(); 43 | // req.body 44 | var username = req.body.username; 45 | var password = req.body.password; 46 | var email = req.body.email; 47 | var fullname = req.body.fullname; 48 | var userTypeCode = req.body.userTypeCode; 49 | // list groups added to user 50 | var groups = req.body.groups; 51 | 52 | if(!username || !password || !email || !fullname || !userTypeCode || !groups){ 53 | return res.status(500).send({ error: 'username , password , email , fullname , userTypeCode , selected groups are required , can not empty' }) 54 | } 55 | 56 | /** 57 | * Validation 58 | * 1- username or email not exist 59 | * 2- is email 60 | * 3- validate password strength 61 | * */ 62 | 63 | var isUserExistsQuery = queries.queryList.IS_USER_EXISTS_QUERY; 64 | var result =await dbConnection.dbQuery(isUserExistsQuery , [username , email]); 65 | console.log("Result : " + JSON.stringify(result)) 66 | if (result.rows[0].count != "0") { 67 | return res.status(500).send({ error: 'User already Exists' }) 68 | } 69 | 70 | if(!validationUtil.isValidEmail(email)){ 71 | return res.status(500).send({ error: 'Email is not valid' }) 72 | } 73 | 74 | if(!validationUtil.isValidPassword(password)){ 75 | return res.status(500).send({ error: 'Password is not valid' }) 76 | } 77 | 78 | // everything is OK 79 | var hashedPassword = await bcrypt.hash(password, 10); 80 | values =[username , hashedPassword , email , userTypeCode , fullname , createdOn , createdBy]; 81 | var saveUserQuery = queries.queryList.SAVE_USER_QUERY; 82 | await dbConnection.dbQuery(saveUserQuery , values); 83 | return res.status(201).send("Successfully adding new user "); 84 | } catch (err) { 85 | console.log("Error : " + err); 86 | return res.status(500).send({error : 'Failed to add new user'}); 87 | } 88 | } -------------------------------------------------------------------------------- /controller/book.controller.js: -------------------------------------------------------------------------------- 1 | var queries = require('../db/queries'); 2 | var dbConnection = require('../db/connection'); 3 | var util = require('../Util/utility'); 4 | var Logger = require('../services/logger.service'); 5 | var auditService = require('../audit/audit.service'); 6 | var auditAction = require('../audit/auditAction'); 7 | var APIError = require('../error/api.error'); 8 | var errorStatus = require('../error/error.status'); 9 | var errorType = require('../error/error.type'); 10 | 11 | const logger = new Logger('book.controller'); 12 | 13 | exports.getBookList = async (req , res) => { 14 | var auditOn = util.dateFormat(); 15 | try { 16 | var bookListQuery = queries.queryList.GET_BOOK_LIST_QUERY; 17 | var result = await dbConnection.dbQuery(bookListQuery); 18 | logger.info("return Book List" , result.rows); 19 | auditService.prepareAudit(auditAction.actionList.GET_BOOK_LIST , result.rows , null , "postman" , auditOn); 20 | return res.status(200).send(JSON.stringify(result.rows)); 21 | } catch (err) { 22 | console.log("Error : " + err); 23 | let errorMessage = 'Failed to get books' + err; 24 | auditService.prepareAudit(auditAction.actionList.GET_BOOK_LIST , null , JSON.stringify(errorMessage) , "postman" , auditOn); 25 | return res.status(500).send({error : 'Failed to get books'}); 26 | } 27 | } 28 | 29 | exports.getBookDetails = async (req , res) => { 30 | try { 31 | var bookId = req.params.bookId; 32 | console.log("bookId : " + bookId); 33 | if (isNaN(bookId)) 34 | throw new APIError(errorType.API_ERROR , 35 | errorStatus.INTERNAL_SERVER_ERROR , 36 | "Invalid bookId , is not a number , bookId value is : " + bookId , 37 | true); 38 | 39 | var bookDetailsQuery = queries.queryList.GET_BOOK_DETAILS_QUERY; 40 | var result = await dbConnection.dbQuery(bookDetailsQuery , [bookId]); 41 | return res.status(200).send(JSON.stringify(result.rows[0])); 42 | } catch (err) { 43 | console.log("Error : " + err.description); 44 | if(err.name === errorType.SQL_INJECTION_ERROR) 45 | // handlerError(); 46 | logger.error("Failed to get Book details " , JSON.stringify(err)); 47 | return res.status(500).send({error : 'Failed to get book details'}); 48 | } 49 | } 50 | 51 | 52 | exports.saveBook = async (req , res) => { 53 | 54 | try { 55 | 56 | var createdBy = "admin"; 57 | var createdOn = new Date(); 58 | // req.body 59 | var title = req.body.title; 60 | var description = req.body.description; 61 | var author = req.body.author; 62 | var publisher = req.body.publisher; 63 | var pages = req.body.pages; 64 | var storeCode = req.body.storeCode; 65 | 66 | // console.log("storeName : " + storeName + " ----- address : " + address) 67 | if(!title || !author || !publisher || !storeCode){ 68 | return res.status(500).send({ error: 'title , author , publisher , storeCode are required , can not empty' }) 69 | } 70 | 71 | values =[title , description , author , publisher , pages , storeCode, createdBy , createdOn]; 72 | var saveBookQuery = queries.queryList.SAVE_BOOK_QUERY; 73 | await dbConnection.dbQuery(saveBookQuery , values); 74 | return res.status(201).send("Successfully adding new book "); 75 | } catch (err) { 76 | console.log("Error : " + err); 77 | return res.status(500).send({error : 'Failed to add new book'}); 78 | } 79 | } 80 | 81 | exports.updateBook = async (req , res) => { 82 | 83 | try { 84 | 85 | var createdBy = "admin"; 86 | var createdOn = new Date(); 87 | // req.body 88 | var bookId=req.body.bookId; 89 | var title = req.body.title; 90 | var description = req.body.description; 91 | var author = req.body.author; 92 | var publisher = req.body.publisher; 93 | var pages = req.body.pages; 94 | var storeCode = req.body.storeCode; 95 | 96 | if(!bookId || !title || !author || !publisher || !storeCode){ 97 | return res.status(500).send({ error: 'bookId , title , author , publisher , storeCode are required , can not empty' }) 98 | } 99 | 100 | values =[title , description , author , publisher , pages , storeCode, createdBy , createdOn , bookId]; 101 | var updateBookQuery = queries.queryList.UPDATE_BOOK_QUERY; 102 | await dbConnection.dbQuery(updateBookQuery , values); 103 | return res.status(200).send("Successfully update book title :" + title); 104 | } catch (err) { 105 | console.log("Error : " + err); 106 | return res.status(500).send({error : 'Failed to update book title : '+ title}); 107 | } 108 | } 109 | 110 | exports.deleteBook = async (req , res) => { 111 | var bookId = req.params.bookId; 112 | 113 | try { 114 | // validate not empty 115 | if(!bookId){ 116 | return res.status(500).send({ error: 'can not delete empty bookId' }) 117 | } 118 | 119 | var deleteBookQuery = queries.queryList.DELETE_BOOK_QUERY; 120 | await dbConnection.dbQuery(deleteBookQuery , [bookId]); 121 | 122 | return res.status(200).send("Successfully book deleted "); 123 | } catch (err) { 124 | console.log("Error : " + err); 125 | return res.status(500).send({error : 'Failed to delete book with id : '+ bookId}); 126 | } 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | } --------------------------------------------------------------------------------