|
Repository: tkssharma/nodejs-microservices-patterns
Branch: master
Commit: 2170453c4faf
Files: 544
Total size: 623.6 KB
Directory structure:
gitextract_2afopmxn/
├── README.md
├── api-gateway-and-service-doscovery/
│ ├── .gitignore
│ ├── README.md
│ ├── ServicesSetup.sh
│ ├── ServicesStart.sh
│ ├── api-gateway/
│ │ ├── Dockerbuild.sh
│ │ ├── Dockerfile
│ │ ├── api/
│ │ │ ├── account/
│ │ │ │ ├── login.js
│ │ │ │ └── signup.js
│ │ │ └── crm/
│ │ │ └── orders/
│ │ │ └── orders.js
│ │ ├── api-gateway.js
│ │ ├── config.js
│ │ ├── config.json
│ │ ├── package.json
│ │ ├── server.js
│ │ └── services-helper.js
│ ├── service-log/
│ │ ├── Dockerbuild.sh
│ │ ├── Dockerfile
│ │ ├── config.js
│ │ ├── config.json
│ │ ├── log.js
│ │ ├── package.json
│ │ └── server.js
│ ├── service-login/
│ │ ├── Dockerbuild.sh
│ │ ├── Dockerfile
│ │ ├── config.js
│ │ ├── config.json
│ │ ├── login.js
│ │ ├── package.json
│ │ └── server.js
│ ├── service-orders/
│ │ ├── Dockerbuild.sh
│ │ ├── Dockerfile
│ │ ├── config.js
│ │ ├── config.json
│ │ ├── orders.js
│ │ ├── package.json
│ │ └── server.js
│ └── service-signup/
│ ├── Dockerbuild.sh
│ ├── Dockerfile
│ ├── config.js
│ ├── config.json
│ ├── package.json
│ ├── server.js
│ └── signup.js
├── dockerized-containers/
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── .travis.yml
│ ├── README.md
│ ├── docker-compose.yml
│ ├── e-Commerce-Admin/
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── app/
│ │ │ ├── config/
│ │ │ │ ├── email.ts
│ │ │ │ └── environments/
│ │ │ │ ├── dev.ts
│ │ │ │ ├── qa.ts
│ │ │ │ └── test.ts
│ │ │ ├── controller/
│ │ │ │ └── UserController.ts
│ │ │ ├── events/
│ │ │ │ └── notification.ts
│ │ │ ├── global/
│ │ │ │ └── templates/
│ │ │ │ ├── emails/
│ │ │ │ │ ├── password-reset-email/
│ │ │ │ │ │ ├── html.pug
│ │ │ │ │ │ └── style.css
│ │ │ │ │ └── welcome-email/
│ │ │ │ │ ├── html.pug
│ │ │ │ │ └── style.css
│ │ │ │ └── response/
│ │ │ │ └── index.ts
│ │ │ ├── helper/
│ │ │ │ ├── bcrypt.ts
│ │ │ │ ├── email.ts
│ │ │ │ ├── errorHandler.ts
│ │ │ │ ├── logger.ts
│ │ │ │ ├── responseTemplate.ts
│ │ │ │ └── twillo.ts
│ │ │ ├── lib/
│ │ │ │ ├── logger.ts
│ │ │ │ ├── mongoose.ts
│ │ │ │ └── requestValidator.ts
│ │ │ ├── middleware/
│ │ │ │ ├── authMiddleware.ts
│ │ │ │ └── requestValidator.ts
│ │ │ ├── models/
│ │ │ │ ├── plugin/
│ │ │ │ │ └── plugin.ts
│ │ │ │ └── user.ts
│ │ │ ├── routes/
│ │ │ │ ├── defaultRoutes.ts
│ │ │ │ ├── provider/
│ │ │ │ │ ├── Facebook.ts
│ │ │ │ │ ├── Google.ts
│ │ │ │ │ ├── Linkedin.ts
│ │ │ │ │ ├── Locale.ts
│ │ │ │ │ └── Twitter.ts
│ │ │ │ ├── routes.ts
│ │ │ │ └── userRoutes.ts
│ │ │ ├── routes.ts
│ │ │ ├── seed/
│ │ │ │ ├── seedUsers.ts
│ │ │ │ └── seedVehicle.ts
│ │ │ ├── transformer/
│ │ │ │ └── userTransformer.ts
│ │ │ └── types/
│ │ │ ├── global.d.ts
│ │ │ └── vendor.d.ts
│ │ ├── env.sh
│ │ ├── express.ts
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── javascripts/
│ │ │ │ └── script.js
│ │ │ └── style.scss
│ │ ├── server.ts
│ │ ├── tsconfig.json
│ │ ├── tslint.json
│ │ └── uploads/
│ │ ├── documents/
│ │ │ └── .gitkeep
│ │ └── profile/
│ │ └── .gitkeep
│ ├── e-Commerce-Auth/
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── app/
│ │ │ ├── config/
│ │ │ │ ├── email.ts
│ │ │ │ └── environments/
│ │ │ │ ├── dev.ts
│ │ │ │ ├── qa.ts
│ │ │ │ └── test.ts
│ │ │ ├── controller/
│ │ │ │ └── UserController.ts
│ │ │ ├── events/
│ │ │ │ └── notification.ts
│ │ │ ├── global/
│ │ │ │ └── templates/
│ │ │ │ ├── emails/
│ │ │ │ │ ├── password-reset-email/
│ │ │ │ │ │ ├── html.pug
│ │ │ │ │ │ └── style.css
│ │ │ │ │ └── welcome-email/
│ │ │ │ │ ├── html.pug
│ │ │ │ │ └── style.css
│ │ │ │ └── response/
│ │ │ │ └── index.ts
│ │ │ ├── helper/
│ │ │ │ ├── bcrypt.ts
│ │ │ │ ├── email.ts
│ │ │ │ ├── errorHandler.ts
│ │ │ │ ├── logger.ts
│ │ │ │ ├── responseTemplate.ts
│ │ │ │ └── twillo.ts
│ │ │ ├── lib/
│ │ │ │ ├── logger.ts
│ │ │ │ ├── mongoose.ts
│ │ │ │ └── requestValidator.ts
│ │ │ ├── middleware/
│ │ │ │ ├── authMiddleware.ts
│ │ │ │ └── requestValidator.ts
│ │ │ ├── models/
│ │ │ │ ├── plugin/
│ │ │ │ │ └── plugin.ts
│ │ │ │ └── user.ts
│ │ │ ├── routes/
│ │ │ │ ├── defaultRoutes.ts
│ │ │ │ ├── provider/
│ │ │ │ │ ├── Facebook.ts
│ │ │ │ │ ├── Google.ts
│ │ │ │ │ ├── Linkedin.ts
│ │ │ │ │ ├── Locale.ts
│ │ │ │ │ └── Twitter.ts
│ │ │ │ ├── routes.ts
│ │ │ │ └── userRoutes.ts
│ │ │ ├── routes.ts
│ │ │ ├── seed/
│ │ │ │ ├── seedUsers.ts
│ │ │ │ └── seedVehicle.ts
│ │ │ ├── transformer/
│ │ │ │ └── userTransformer.ts
│ │ │ └── types/
│ │ │ ├── global.d.ts
│ │ │ └── vendor.d.ts
│ │ ├── env.sh
│ │ ├── express.ts
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── javascripts/
│ │ │ │ └── script.js
│ │ │ └── style.scss
│ │ ├── server.ts
│ │ ├── tsconfig.json
│ │ ├── tslint.json
│ │ └── uploads/
│ │ ├── documents/
│ │ │ └── .gitkeep
│ │ └── profile/
│ │ └── .gitkeep
│ ├── e-Commerce-Cart/
│ │ ├── .sequelizerc
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── app/
│ │ │ ├── config/
│ │ │ │ └── environments/
│ │ │ │ ├── dev.ts
│ │ │ │ ├── qa.ts
│ │ │ │ └── test.ts
│ │ │ ├── events/
│ │ │ │ └── processEvent.ts
│ │ │ ├── helper/
│ │ │ │ ├── errorHandler.ts
│ │ │ │ ├── errors.ts
│ │ │ │ ├── logger.ts
│ │ │ │ └── responseTemplate.ts
│ │ │ ├── lib/
│ │ │ │ ├── logger.ts
│ │ │ │ ├── mysql.ts
│ │ │ │ └── requestValidator.ts
│ │ │ ├── middleware/
│ │ │ │ └── requestValidator.ts
│ │ │ ├── models/
│ │ │ │ └── data/
│ │ │ │ └── cart.ts
│ │ │ ├── routes/
│ │ │ │ └── defaultRoutes.ts
│ │ │ ├── routes.ts
│ │ │ └── types/
│ │ │ ├── global.d.ts
│ │ │ └── vendor.d.ts
│ │ ├── config/
│ │ │ └── config.js
│ │ ├── env.sh
│ │ ├── express.ts
│ │ ├── mysql/
│ │ │ └── schema.sql
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── javascripts/
│ │ │ │ └── script.js
│ │ │ └── style.scss
│ │ ├── server.ts
│ │ ├── tsconfig.json
│ │ ├── tslint.json
│ │ └── uploads/
│ │ ├── documents/
│ │ │ └── .gitkeep
│ │ └── profile/
│ │ └── .gitkeep
│ ├── e-Commerce-Client/
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── env.sh
│ │ ├── firebase.json
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── index.html
│ │ │ ├── manifest.json
│ │ │ └── normalize.css
│ │ └── src/
│ │ ├── api/
│ │ │ └── index.js
│ │ ├── components/
│ │ │ ├── App/
│ │ │ │ └── index.js
│ │ │ ├── Checkbox/
│ │ │ │ └── index.js
│ │ │ ├── FloatCart/
│ │ │ │ ├── CartProduct/
│ │ │ │ │ └── index.js
│ │ │ │ ├── index.js
│ │ │ │ └── style.scss
│ │ │ ├── Selectbox/
│ │ │ │ └── index.js
│ │ │ ├── Shelf/
│ │ │ │ ├── Filter/
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── style.scss
│ │ │ │ ├── ProductList/
│ │ │ │ │ ├── Product/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── ShelfHeader/
│ │ │ │ │ └── index.js
│ │ │ │ ├── Sort/
│ │ │ │ │ └── index.js
│ │ │ │ ├── index.js
│ │ │ │ └── style.scss
│ │ │ ├── Spinner/
│ │ │ │ ├── index.js
│ │ │ │ └── style.scss
│ │ │ └── Thumb/
│ │ │ └── index.js
│ │ ├── config/
│ │ │ ├── index.js
│ │ │ └── server.js
│ │ ├── index.js
│ │ ├── index.scss
│ │ ├── layout/
│ │ │ ├── Auth.js
│ │ │ └── Public.js
│ │ ├── services/
│ │ │ ├── auth/
│ │ │ │ ├── Login.js
│ │ │ │ ├── Logout.js
│ │ │ │ ├── Register.js
│ │ │ │ ├── ResetPassword.js
│ │ │ │ ├── ValidateToken.js
│ │ │ │ ├── action.js
│ │ │ │ ├── actionTypes.js
│ │ │ │ ├── auth.scss
│ │ │ │ └── reducer.js
│ │ │ ├── cart/
│ │ │ │ ├── actionTypes.js
│ │ │ │ ├── actions.js
│ │ │ │ └── reducer.js
│ │ │ ├── filters/
│ │ │ │ ├── actionTypes.js
│ │ │ │ ├── actions.js
│ │ │ │ └── reducer.js
│ │ │ ├── reducers.js
│ │ │ ├── shelf/
│ │ │ │ ├── actionTypes.js
│ │ │ │ ├── actions.js
│ │ │ │ └── reducer.js
│ │ │ ├── sort/
│ │ │ │ ├── actionTypes.js
│ │ │ │ ├── actions.js
│ │ │ │ └── reducer.js
│ │ │ ├── store.js
│ │ │ ├── total/
│ │ │ │ ├── actionTypes.js
│ │ │ │ ├── actions.js
│ │ │ │ └── reducer.js
│ │ │ └── util.js
│ │ ├── setupTests.js
│ │ └── util/
│ │ ├── helper/
│ │ │ └── index.js
│ │ └── middleware/
│ │ ├── auth.js
│ │ └── index.js
│ └── proxy/
│ ├── default.conf
│ ├── hosts
│ └── ssl/
│ ├── pac.crt
│ └── pac.key
├── event-driven-microservices-docker/
│ ├── .githooks/
│ │ ├── pre-commit
│ │ ├── pre-commit.d/
│ │ │ ├── articles-management-service
│ │ │ ├── events-management-service
│ │ │ ├── notification-service
│ │ │ └── user-management-service
│ │ ├── pre-push
│ │ └── pre-push.d/
│ │ ├── articles-management-service
│ │ ├── events-management-service
│ │ ├── notification-service
│ │ └── user-management-service
│ ├── .gitignore
│ ├── docker-compose.yml
│ ├── run_all_tests
│ └── services/
│ ├── articles-management/
│ │ ├── .dockerignore
│ │ ├── .eslintignore
│ │ ├── .eslintrc.yml
│ │ ├── .gitignore
│ │ ├── Dockerfile
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── app.js
│ │ │ ├── controllers/
│ │ │ │ ├── __mocks__/
│ │ │ │ │ └── article.controller.js
│ │ │ │ └── article.controller.js
│ │ │ ├── environment/
│ │ │ │ └── config.js
│ │ │ ├── message-bus/
│ │ │ │ └── send/
│ │ │ │ ├── __mocks__/
│ │ │ │ │ └── article.added.js
│ │ │ │ └── article.added.js
│ │ │ ├── middlewares/
│ │ │ │ ├── __mocks__/
│ │ │ │ │ └── jwt.js
│ │ │ │ └── jwt.js
│ │ │ ├── models/
│ │ │ │ ├── __mocks__/
│ │ │ │ │ └── article.model.js
│ │ │ │ └── article.model.js
│ │ │ ├── routes/
│ │ │ │ └── article.routes.js
│ │ │ └── server.js
│ │ └── tests/
│ │ └── unit/
│ │ ├── __snapshots__/
│ │ │ └── article.added.message.send.test.js.snap
│ │ ├── app.test.js
│ │ ├── article.added.message.send.test.js
│ │ ├── article.controller.test.js
│ │ ├── article.model.test.js
│ │ ├── article.routes.test.js
│ │ ├── config.test.js
│ │ └── server.test.js
│ ├── authentication/
│ │ ├── .dockerignore
│ │ ├── .eslintrc.yml
│ │ ├── .gitignore
│ │ ├── .gitkeep
│ │ ├── .snyk
│ │ ├── Dockerfile
│ │ ├── package.json
│ │ └── src/
│ │ ├── app.js
│ │ ├── controllers/
│ │ │ └── auth.controller.js
│ │ ├── environment/
│ │ │ └── config.js
│ │ ├── message-bus/
│ │ │ └── recieve/
│ │ │ └── user.added.js
│ │ ├── models/
│ │ │ └── auth.model.js
│ │ ├── routes/
│ │ │ └── auth.routes.js
│ │ └── server.js
│ ├── events-management/
│ │ ├── .dockerignore
│ │ ├── .eslintrc.yml
│ │ ├── .gitignore
│ │ ├── Dockerfile
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── app.js
│ │ │ ├── controllers/
│ │ │ │ ├── __mocks__/
│ │ │ │ │ └── event.controller.js
│ │ │ │ └── event.controller.js
│ │ │ ├── environment/
│ │ │ │ └── config.js
│ │ │ ├── middlewares/
│ │ │ │ ├── __mocks__/
│ │ │ │ │ └── jwt.js
│ │ │ │ └── jwt.js
│ │ │ ├── models/
│ │ │ │ ├── __mocks__/
│ │ │ │ │ └── event.model.js
│ │ │ │ └── event.model.js
│ │ │ ├── routes/
│ │ │ │ └── event.routes.js
│ │ │ └── server.js
│ │ └── tests/
│ │ └── unit/
│ │ ├── app.test.js
│ │ ├── config.test.js
│ │ ├── event.controller.test.js
│ │ ├── event.model.test.js
│ │ ├── event.routes.test.js
│ │ └── server.test.js
│ ├── media-management/
│ │ └── .gitkeep
│ ├── notification/
│ │ ├── .eslintrc.yml
│ │ ├── .gitignore
│ │ ├── Dockerfile
│ │ ├── __mocks__/
│ │ │ ├── amqp-ts-async.js
│ │ │ ├── koa.js
│ │ │ ├── nodemailer.js
│ │ │ └── winston.js
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── environment/
│ │ │ │ └── config.js
│ │ │ ├── message-controllers/
│ │ │ │ ├── __mocks__/
│ │ │ │ │ └── articles.js
│ │ │ │ └── articles.js
│ │ │ ├── modules/
│ │ │ │ └── email/
│ │ │ │ ├── __mocks__/
│ │ │ │ │ ├── email.js
│ │ │ │ │ └── email.templates.js
│ │ │ │ ├── email.js
│ │ │ │ └── email.templates.js
│ │ │ ├── server.js
│ │ │ └── subscriptions/
│ │ │ ├── __mocks__/
│ │ │ │ └── article.added.js
│ │ │ └── article.added.js
│ │ └── tests/
│ │ └── unit/
│ │ ├── __snapshots__/
│ │ │ ├── config.test.js.snap
│ │ │ ├── email.templates.test.js.snap
│ │ │ └── email.test.js.snap
│ │ ├── article.added.subscription.test.js
│ │ ├── article.message.controller.test.js
│ │ ├── config.test.js
│ │ ├── email.templates.test.js
│ │ ├── email.test.js
│ │ └── server.test.js
│ ├── search/
│ │ └── .gitkeep
│ └── user-management/
│ ├── .dockerignore
│ ├── .eslintrc.yml
│ ├── .gitignore
│ ├── .gitkeep
│ ├── Dockerfile
│ ├── __mocks__/
│ │ ├── amqp-ts-async.js
│ │ └── winston.js
│ ├── package.json
│ ├── src/
│ │ ├── app.js
│ │ ├── controllers/
│ │ │ ├── __mocks__/
│ │ │ │ └── user.controller.js
│ │ │ └── user.controller.js
│ │ ├── environment/
│ │ │ └── config.js
│ │ ├── message-bus/
│ │ │ └── send/
│ │ │ └── user.added.js
│ │ ├── middlewares/
│ │ │ ├── __mocks__/
│ │ │ │ └── jwt.js
│ │ │ └── jwt.js
│ │ ├── models/
│ │ │ ├── __mocks__/
│ │ │ │ └── user.model.js
│ │ │ └── user.model.js
│ │ ├── routes/
│ │ │ └── user.routes.js
│ │ └── server.js
│ └── tests/
│ └── unit/
│ ├── __snapshots__/
│ │ ├── user.added.message.send.test.js.snap
│ │ └── user.controller.test.js.snap
│ ├── app.test.js
│ ├── config.test.js
│ ├── server.test.js
│ ├── user.added.message.send.test.js
│ ├── user.controller.test.js
│ ├── user.model.test.js
│ └── user.routes.test.js
├── node js-with-serverless/
│ ├── .gitignore
│ ├── README.md
│ ├── functions/
│ │ ├── delete_item.ts
│ │ ├── edit_item.ts
│ │ ├── read_all.ts
│ │ ├── read_single_item.ts
│ │ └── write_item.ts
│ ├── models/
│ │ └── table_schema.ts
│ ├── package.json
│ ├── serverless.yml
│ └── shared/
│ ├── create_dynamo.ts
│ └── update_dynamo.ts
├── node-js-lambda-sqs-serverless/
│ ├── .gitignore
│ ├── README.md
│ ├── data.json
│ ├── db.js
│ ├── handler.js
│ ├── models/
│ │ └── note.js
│ ├── package.json
│ ├── serverless.yml
│ └── sqs.js
├── node-microservice-starter/
│ ├── .dockerignore
│ ├── .editorconfig
│ ├── .gitattributes
│ ├── .gitignore
│ ├── README.md
│ ├── docker-compose.yml
│ ├── nginx/
│ │ ├── Dockerfile
│ │ └── nginx.conf
│ └── users/
│ ├── .eslintrc.js
│ ├── .prettierrc
│ ├── Dockerfile
│ ├── README.md
│ ├── nest-cli.json
│ ├── package.json
│ ├── src/
│ │ ├── app.controller.spec.ts
│ │ ├── app.controller.ts
│ │ ├── app.module.ts
│ │ ├── app.service.ts
│ │ └── main.ts
│ ├── test/
│ │ ├── app.e2e-spec.ts
│ │ └── jest-e2e.json
│ ├── tsconfig.build.json
│ └── tsconfig.json
├── nodejs-cqrs-pattern/
│ ├── .dockerignore
│ ├── .gitignore
│ ├── Dockerfile
│ ├── README.md
│ ├── config.ts
│ ├── docker-compose.yml
│ ├── docs/
│ │ └── README.md
│ ├── githooks/
│ │ └── README.md
│ ├── nest-cli.json
│ ├── nodemon-debug.json
│ ├── nodemon.json
│ ├── package.json
│ ├── scripts/
│ │ ├── down.sh
│ │ └── up.sh
│ ├── src/
│ │ ├── app.module.ts
│ │ ├── core/
│ │ │ └── event-store/
│ │ │ ├── event-store.class.ts
│ │ │ ├── event-store.interface.ts
│ │ │ ├── event-store.module.ts
│ │ │ ├── event-store.provider.ts
│ │ │ └── event-store.ts
│ │ ├── main.ts
│ │ └── users/
│ │ ├── commands/
│ │ │ ├── handlers/
│ │ │ │ ├── create-user.handler.ts
│ │ │ │ ├── delete-user.handler.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── update-user.handler.ts
│ │ │ │ └── welcome-user.handler.ts
│ │ │ └── impl/
│ │ │ ├── create-user.command.ts
│ │ │ ├── delete-user.command.ts
│ │ │ ├── update-user.command.ts
│ │ │ └── welcome-user.command.ts
│ │ ├── controllers/
│ │ │ ├── users.controller.spec.ts
│ │ │ └── users.controller.ts
│ │ ├── dtos/
│ │ │ └── users.dto.ts
│ │ ├── events/
│ │ │ ├── handlers/
│ │ │ │ ├── index.ts
│ │ │ │ ├── user-created.handler.ts
│ │ │ │ ├── user-deleted.handler.ts
│ │ │ │ ├── user-updated.handler.ts
│ │ │ │ └── user-welcomed.handler.ts
│ │ │ └── impl/
│ │ │ ├── user-created.event.ts
│ │ │ ├── user-deleted.event.ts
│ │ │ ├── user-updated.event.ts
│ │ │ └── user-welcomed.event.ts
│ │ ├── models/
│ │ │ └── user.model.ts
│ │ ├── repository/
│ │ │ └── user.repository.ts
│ │ ├── sagas/
│ │ │ └── users.sagas.ts
│ │ ├── services/
│ │ │ └── users.service.ts
│ │ └── users.module.ts
│ ├── test/
│ │ ├── app.e2e-spec.ts
│ │ └── jest-e2e.json
│ ├── tsconfig.json
│ ├── tsconfig.spec.json
│ └── tslint.json
├── nodejs-express-typescript/
│ ├── .editorconfig
│ ├── .eslintignore
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── .prettierrc.json
│ ├── LICENSE
│ ├── Procfile
│ ├── README.md
│ ├── jest.config.js
│ ├── nodemon.json
│ ├── package.json
│ ├── src/
│ │ ├── api/
│ │ │ ├── index.ts
│ │ │ ├── middlewares/
│ │ │ │ ├── index.ts
│ │ │ │ └── isAuth.ts
│ │ │ └── routes/
│ │ │ └── auth.ts
│ │ ├── app.ts
│ │ ├── config/
│ │ │ └── index.ts
│ │ ├── interfaces/
│ │ │ └── IUser.ts
│ │ ├── loaders/
│ │ │ ├── dependencyInjector.ts
│ │ │ ├── express.ts
│ │ │ ├── index.ts
│ │ │ ├── logger.ts
│ │ │ └── mongoose.ts
│ │ ├── models/
│ │ │ └── user.ts
│ │ ├── services/
│ │ │ └── auth.ts
│ │ └── types/
│ │ └── express/
│ │ └── index.d.ts
│ ├── tests/
│ │ ├── .gitkeep
│ │ ├── sample.test.ts
│ │ └── services/
│ │ └── .gitkeep
│ └── tsconfig.json
├── nodejs-microservice-using-docker-Part-1/
│ ├── .gitignore
│ ├── .travis.yml
│ ├── docker-compose.yml
│ ├── nginx/
│ │ ├── Dockerfile
│ │ └── nginx.conf
│ └── server/
│ ├── .babelrc
│ ├── .editorconfig
│ ├── .gitignore
│ ├── .jshintrc
│ ├── .jshintrc-spec
│ ├── Dockerfile
│ ├── Procfile
│ ├── api/
│ │ ├── service/
│ │ │ ├── index.js
│ │ │ ├── index.spec.js
│ │ │ ├── service.controller.js
│ │ │ ├── service.events.js
│ │ │ ├── service.integration.js
│ │ │ ├── service.model.js
│ │ │ └── service.socket.js
│ │ └── utils.js
│ ├── app.js
│ ├── config/
│ │ ├── app.conf.js
│ │ ├── db.conf.js
│ │ ├── routes.conf.js
│ │ └── socket.conf.js
│ ├── gulpfile.babel.js
│ ├── index.js
│ ├── mocha.conf.js
│ └── package.json
└── nodejs-microservice-using-docker-Part-2/
├── .gitignore
├── docker-compose.yml
├── nginx/
│ ├── Dockerfile
│ ├── Dockerfile_custom
│ └── nginx.conf
├── node/
│ ├── Dockerfile
│ ├── index.js
│ ├── package.json
│ └── test/
│ └── dummyTest.js
└── redis/
└── Dockerfile
================================================
FILE CONTENTS
================================================
================================================
FILE: README.md
================================================
# nodejs-microservces-patterns
nodejs-microservces-patterns
- Simple Microservices Demo
- Simple Auth and Autnz setup
- CQRS Pattern
- Event Driven Design Pattern
### Different examples for understanding node js with microservoces Patterns
#### https://www.youtube.com/watch?v=_pO0sDeQrp0&list=PLIGDNOJWiL182j1bD_nQm-SxARR5s977O&ab_channel=CodeLabs
================================================
FILE: api-gateway-and-service-doscovery/.gitignore
================================================
node_modules
docs
node/node_modules
.DS_Store
node/npm-debug.log
.DS_Store
================================================
FILE: api-gateway-and-service-doscovery/README.md
================================================
#What is this?
This porject/turotial explains how to implement a NodeJs Api Gateway, into a Microservices Architecture based on a Service Registry developed with a server-side discovery pattern.

Actually, this project can be described as a complete Microservices Architecture containing four different microservices accessible via Api Gateway and discovered with a Service Registry.
#How to setup and configure
To setup the project, it is enough to launch the the bash script ServicesSetup.sh
The configuration it is a bit tedious but it is very easy. In order you need to open all the config.json file that you will find in to each project folder (services and api-gateway) and setup the MondoDB configuration within the serviceRegistry object:
```javascript
"serviceRegistry":{
"watchDog":{
"isEnabled":false,
"timer":30000
},
"database":{
"name":"my_mongo_db",
"user":"my_mongo_db_user",
"password":"my_mongo_db_password",
"host":"my_mongo_db_host",
"port":27017
}
}
```
A more dtailed description of the configuration is reported in to the section at the bottom of this document.
#How to use
To start all services you must launch the bash script ServicesStart.sh. This script will provide to launch five differente clustered instances of a Node server as reported below:
Service |Port | Service Route | Api Gateway Ruote (8080)
----------------|------------|---------------|-------------------------
service-login | 8081 | /api/login | /api/account/login
service-signup | 8082 | /api/signup | /api/account/signup
service-orders | 8084 | /api/orders | /api/crm/orders
service-log | 8084 | /api/log | -----
api-gateway | 8080 | ---- | -----
For this tutorial, it is allowed to access directly (see Service Route) to the services, but, depending of your requirements, you can block this access, alllowing only the access via Api Gateway (see Api Gateway Ruote) that for this project is listening to the port 8080.
#Api Gateway Configuraiton
Here, a detailed description of the config.json file for the Pai Gateway
```javascript
{
"server":{
"id":"MicroNodeApiGateway",
"port":8080,
"isCluster":true,
"https":{
"isEnabled":false,
"key":"",
"ca":""
},
"headers":[
{"name":"Access-Control-Allow-Origin","value":"*"},
{"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"},
{"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"}
]
},
"api":{
"route":"api",
"modules":[
{"name":"login", "path":"api/account", "route":"account/login"},
{"name":"signup", "path":"api/account", "route":"account/signup"},
{"name":"orders", "path":"api/crm/orders", "route":"crm/orders"}
]
},
"services":[
{"name":"ServiceLog", "endpointId":"log"},
{"name":"ServiceLogin", "endpointId":"login"},
{"name":"ServiceSignup", "endpointId":"signup"},
{"name":"ServiceOrders", "endpointId":"orders"}
],
"serviceRegistry":{
"database":{
"name":"my_mongo_db",
"user":"my_mongo_db_user",
"password":"my_mongo_db_password",
"host":"my_mongo_db_host",
"port":27017
}
}
}
```
where:
- server.id: it is a key to identify the microservice
- server.port: it is the port where the microservice is listen to
- server,isCluster: set true if you want you fork the main process depending of your CPU
- server.https: enable/disable the https. It is needed to have the righ certificates to allow clients to connect under https
- server.headers: put here all the response headers that you want to use, for example to enable the cross-origin resource sharing.
- api.route: defines the main route of the api (e.g. /api)
- api.modules: add in to this array all the module (js files for example Express middleware) that you want to use as api modules.
- api.services: add in to this array all the services that you want to implement with your Api Gateway using as service name and entry poin id, the same values used to register a microservice in to the service registry (see below Microservice Configuration and for more detail take a look to this project https://github.com/alchimya/micro-node-service/edit/master/README.md).
- serviceRegistry.watchDog: enable/disable the auto-update for the service registry. Speficy the update seconds into the timer property
- serviceRegistry.databse: configure here your MongoDb connection params. This database represents your Service Registry
#Microservice Configuraiton
Here, a detailed description of the config.json file for a Microservice
```javascript
{
"server":{
"id":"MicroNodeService",
"port":8080,
"isCluster":true,
"https":{
"isEnabled":false,
"key":"",
"ca":""
},
"headers":[
{"name":"Access-Control-Allow-Origin","value":"*"},
{"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"},
{"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"}
]
},
"api":{
"route":"api",
"modules":[
{"name":"login", "route":"login"}
]
},
"serviceRegistry":{
"watchDog":{
"isEnabled":false,
"timer":30000
},
"database":{
"name":"my_mongo_db",
"user":"my_mongo_db_user",
"password":"my_mongo_db_password",
"host":"my_mongo_db_host",
"port":27017
}
}
}
```
where:
- server.id: it is a key to identify the microservice
- server.port: it is the port where the microservice is listen to
- server,isCluster: set true if you want you fork the main process depending of your CPU
- server.https: enable/disable the https. It is needed to have the righ certificates to allow clients to connect under https
- server.headers: put here all the response headers that you want to use, for example to enable the cross-origin resource sharing.
- api.route: defines the main route of the api (e.g. /api)
- api.modules: add in to this array all the module (js files for example Express middleware) that you want to use as api modules
- serviceRegistry.watchDog: enable/disable the auto-update for the service registry. Speficy the update seconds into the timer property
- serviceRegistry.databse: configure here your MongoDb connection params. This database represents your Service Registry

================================================
FILE: api-gateway-and-service-doscovery/ServicesSetup.sh
================================================
cd service-login
sudo npm install
cd ..
cd service-orders
sudo npm install
cd ..
cd service-signup
sudo npm install
cd ..
cd service-log
sudo npm install
cd ..
cd api-gateway
sudo npm install
================================================
FILE: api-gateway-and-service-doscovery/ServicesStart.sh
================================================
cd service-login
DEBUG=http node server &
cd ..
cd service-orders
DEBUG=http node server &
cd ..
cd service-signup
DEBUG=http node server &
cd ..
cd service-log
DEBUG=http node server &
cd ..
cd api-gateway
DEBUG=http node server
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/Dockerbuild.sh
================================================
docker build -t micro-node-service-api-gateway:latest .
winpty docker run -it --rm -p 8080:8080 --name micro-node-service-api-gateway micro-node-service-api-gateway:latest
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/Dockerfile
================================================
FROM node:6.2.0-onbuild
EXPOSE 8080
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/api/account/login.js
================================================
/**
* Created by domenicovacchiano on 10/07/16.
*/
var express = require('express'),
router = express.Router(),
apiGateway = require('../.././api-gateway');
router.post('/', function (req, res,next) {
var request = new apiGateway();
request.sendRequest("ServiceLogin","login",req, res,next);
});
module.exports = router;
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/api/account/signup.js
================================================
/**
* Created by domenicovacchiano on 10/07/16.
*/
var express = require('express'),
router = express.Router(),
apiGateway = require('../.././api-gateway');
router.post('/', function (req, res,next) {
var request = new apiGateway();
request.sendRequest("ServiceSignup","signup",req, res,next);
});
module.exports = router;
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/api/crm/orders/orders.js
================================================
/**
* Created by domenicovacchiano on 10/07/16.
*/
var express = require('express'),
router = express.Router(),
apiGateway = require('../../.././api-gateway');
router.post('/', function (req, res,next) {
var request = new apiGateway();
request.sendRequest("ServiceOrders","orders",req, res,next);
});
module.exports = router;
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/api-gateway.js
================================================
/**
* Created by domenicovacchiano on 10/07/16.
*/
var debug = require('debug')('http'),
config= require ('./config')(),
request = require('request'),
servicesHelper = require('./services-helper')(config.services),
serviceRegistry = require ('micro-node-service-registry-lib')({
name:config.serviceRegistry.database.name,
user:config.serviceRegistry.database.user,
password:config.serviceRegistry.database.password,
host:config.serviceRegistry.database.host,
port:config.serviceRegistry.database.port,
connectionPool:config.serviceRegistry.database.connectionPool
});
var ApiGateway = function () {
};
ApiGateway.prototype.sendRequest=function (serviceName,serviceEndpointId,req, res,next) {
service=servicesHelper.getService(serviceName,serviceEndpointId);
serviceRegistry.find(service.name,service.endpointId,function (error,service) {
if (service && !error){
console.log(service);
request({
url: service.endpointUrl,
method: 'POST',
json:req.body
}, function(error, response, body){
if (error){
return next(error)
}else {
debug(body);
return res.status(response.statusCode).send(body);
}
});
} else {
if (error){
return next(error);
}else {
return res.status(500).send(responseLib.errorResponse(1001,"Service not found","Application Error"));
}
}
});
};
module.exports=ApiGateway;
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/config.js
================================================
/**
* Created by domenicovacchiano on 25/05/16.
*/
var fs = require('fs');
function Config() {
var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8');
return{
server:{
id:config.server.id,
port:config.server.port,
isCluster:config.server.isCluster,
https:config.server.https,
headers:config.server.headers,
httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null,
httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null,
},
api:{
route:config.api.route,
modules:config.api.modules
},
services:config.services,
serviceRegistry:config.serviceRegistry
};
}
module.exports=Config;
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/config.json
================================================
{
"server":{
"id":"MicroNodeApiGateway",
"port":8080,
"isCluster":true,
"https":{
"isEnabled":false,
"key":"",
"ca":""
},
"headers":[
{"name":"Access-Control-Allow-Origin","value":"*"},
{"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"},
{"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"}
]
},
"api":{
"route":"api",
"modules":[
{"name":"login", "path":"api/account", "route":"account/login"},
{"name":"signup", "path":"api/account", "route":"account/signup"},
{"name":"orders", "path":"api/crm/orders", "route":"crm/orders"}
]
},
"services":[
{"name":"ServiceLog", "endpointId":"log"},
{"name":"ServiceLogin", "endpointId":"login"},
{"name":"ServiceSignup", "endpointId":"signup"},
{"name":"ServiceOrders", "endpointId":"orders"}
],
"serviceRegistry":{
"database":{
"name":"test",
"user":"",
"password":"",
"host":"192.168.29.43",
"port":27017
}
}
}
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/package.json
================================================
{
"name": "DoorApiGateway",
"version": "0.0.1",
"description": "Api Gateway",
"author": {
"name": "Domenico Vacchiano",
"email": "domenico@doorgames.com",
"url": "http://www.doorgames.com"
},
"homepage": "http://www.doorgames.com/",
"repository": {
"type": "git",
"url": ""
},
"engines": {
"node": ">= 0.6.0",
"npm": ">= 1.0.0"
},
"dependencies": {
"express": "^4.13.4",
"body-parser": "^1.15.1",
"jsonwebtoken": "^7.0.0",
"request": "^2.72.0",
"morgan": "^1.7.0",
"micro-node-net-lib": "git@github.com:alchimya/micro-node-net-lib.git",
"micro-node-service-registry-lib": "git@github.com:alchimya/micro-node-service-registry-lib.git"
},
"private": true,
"scripts": {
"start": "node server.js"
},
"main": "server.js"
}
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/server.js
================================================
/**
* Created by domenicovacchiano on 10/07/16.
*/
var config= require ('./config')(),
express=require('express'),
debug = require('debug')('http'),
bodyParser = require('body-parser'),
morgan= require('morgan'),
cluster = require('cluster'),
numCPUs = require('os').cpus().length,
netLib = require ('micro-node-net-lib'),
apiGateway = require('./api-gateway'),
configServer= {
server:{
port:config.server.port
},
https:{
isEnabled:config.server.https.isEnabled,
key:config.server.httpsKeyContent,
ca:config.server.httpsCaContent
},
express:{
app:null
},
exitHandlers:["exit","SIGINT","SIGTERM"]
},
server = netLib.server(configServer);
if (cluster.isMaster && config.server.isCluster) {
debug("cpus:" + numCPUs);
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log("cluster exit");
debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code);
cluster.fork();
});
} else {
var app=express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('dev'));
configServer.express.app = app;
//header(s) setting
app.all('/*', function(req, res, next) {
config.server.headers.forEach(function(item) {
//console.log(item);
res.header(item.name, item.value);
});
next();
});
//pu here a middleware to check the api key
//load API route(s)
config.api.modules.forEach(function(item) {
//console.log(item);
app.use('/' + config.api.route + "/" + item.route, require('./' + item.path + "/" + item.name));
});
server.create(function (err,server) {
if (!err){
console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " +
config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : ""));
} else {
debug(err);
}
});
//Http Error Handling on
app.use(function(err, req, res, next) {
debug(err);
var request = new apiGateway();
request.sendRequest("ServiceLog","log",req, res,next);
res.status(500).send({
code:1000,
message:"Application Error",
domain:"Application Error"
});
});
}
================================================
FILE: api-gateway-and-service-doscovery/api-gateway/services-helper.js
================================================
/**
* Created by domenicovacchiano on 11/07/16.
*/
function ServiceHelper(services) {
return{
getServiceWithName:function (serviceName) {
var service=services.filter(function( item ) {
return item.name == serviceName;
});
if (!service || !service[0] || service[0].length==0){
return null;
}
return service[0];
},
getService:function (serviceName,serviceEndpointId) {
var service=services.filter(function( item ) {
return (item.name == serviceName && item.endpointId == serviceEndpointId);
});
if (!service || !service[0] || service[0].length==0){
return null;
}
return service[0];
}
};
};
module.exports=ServiceHelper;
================================================
FILE: api-gateway-and-service-doscovery/service-log/Dockerbuild.sh
================================================
docker build -t micro-node-service-log:latest .
winpty docker run -it --rm -p 8084:8084 --name micro-node-service-log micro-node-service-log:latest
================================================
FILE: api-gateway-and-service-doscovery/service-log/Dockerfile
================================================
FROM node:6.2.0-onbuild
EXPOSE 8084
================================================
FILE: api-gateway-and-service-doscovery/service-log/config.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var fs = require('fs');
function Config() {
var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8');
return{
server:{
id:config.server.id,
port:config.server.port,
isCluster:config.server.isCluster,
https:config.server.https,
headers:config.server.headers,
httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null,
httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null,
},
api:{
route:config.api.route,
modules:config.api.modules
},
serviceRegistry:config.serviceRegistry
};
}
module.exports=Config;
================================================
FILE: api-gateway-and-service-doscovery/service-log/config.json
================================================
{
"server":{
"id":"ServiceLog",
"port":8084,
"isCluster":true,
"https":{
"isEnabled":false,
"key":"",
"ca":""
},
"headers":[
{"name":"Access-Control-Allow-Origin","value":"*"},
{"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"},
{"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"}
]
},
"api":{
"route":"api",
"modules":[
{"name":"log", "route":"log"}
]
},
"serviceRegistry":{
"watchDog":{
"isEnabled":false,
"timer":30000
},
"database":{
"name":"my_mongo_db",
"user":"my_mongo_db_user",
"password":"my_mongo_db_password",
"host":"my_mongo_db_host",
"port":27017
}
}
}
================================================
FILE: api-gateway-and-service-doscovery/service-log/log.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var express = require('express'),
router = express.Router(),
debug = require('debug')('http'),
config= require ('./config')()
router.post('/', function (req, res,next) {
return res.status(200).send("## Log -> This is just a test response ;-)");
});
module.exports = router;
================================================
FILE: api-gateway-and-service-doscovery/service-log/package.json
================================================
{
"name": "MicroNodeService",
"version": "0.0.1",
"description": "Micro Node Tutorial",
"author": {
"name": "Domenico Vacchiano",
"email": "info@domenicovacchiano.com",
"url": "http://www.domenicovacchiano.com"
},
"homepage": "http://www.domenicovacchiano.com/",
"repository": {
"type": "git",
"url": ""
},
"engines": {
"node": ">= 0.6.0",
"npm": ">= 1.0.0"
},
"dependencies": {
"express": "^4.13.4",
"body-parser": "^1.15.1",
"request": "^2.72.0",
"morgan": "^1.7.0",
"network-address": "^1.1.0",
"micro-node-net-lib": "git@github.com:alchimya/micro-node-net-lib.git",
"micro-node-service-registry-lib": "git@github.com:alchimya/micro-node-service-registry-lib.git"
},
"private": true,
"scripts": {
"start": "node server.js"
},
"main": "server.js"
}
================================================
FILE: api-gateway-and-service-doscovery/service-log/server.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var config= require ('./config')(),
address = require('network-address'),
express=require('express'),
debug = require('debug')('http'),
bodyParser = require('body-parser'),
morgan= require('morgan'),
cluster = require('cluster'),
numCPUs = require('os').cpus().length,
netLib = require ('micro-node-net-lib'),
configServer= {
server:{
port:config.server.port
},
https:{
isEnabled:config.server.https.isEnabled,
key:config.server.httpsKeyContent,
ca:config.server.httpsCaContent
},
express:{
app:null
},
exitHandlers:["exit","SIGINT","SIGTERM"]
}
server = netLib.server(configServer),
serviceRegistry = require ('micro-node-service-registry-lib')({
name:config.serviceRegistry.database.name,
user:config.serviceRegistry.database.user,
password:config.serviceRegistry.database.password,
host:config.serviceRegistry.database.host,
port:config.serviceRegistry.database.port,
connectionPool:config.serviceRegistry.database.connectionPool
});
if (cluster.isMaster && config.server.isCluster) {
debug("cpus:" + numCPUs);
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log("cluster exit");
debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code);
cluster.fork();
});
} else {
var app=express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('dev'));
configServer.express.app = app;
//header(s) setting
app.all('/*', function(req, res, next) {
config.server.headers.forEach(function(item) {
//console.log(item);
res.header(item.name, item.value);
});
next();
});
//load API route(s)
config.api.modules.forEach(function(item) {
//console.log(item);
app.use('/' + config.api.route + "/" + item.route, require('./' + item.name));
});
server.create(function (err,server) {
if (!err){
//load API route(s) and register services
registerServer();
if (config.serviceRegistry.watchDog.isEnabled){
setInterval(function(){
registerServer();
}, config.serviceRegistry.watchDog.timer);
}
console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " +
config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : ""));
} else {
debug(err);
}
});
server.registerExitHandler(function () {
unregisterServer();
debug("Server Exit Handled");
});
var registerServer=function () {
if (!config.server.isCluster || cluster.worker.id===1){
debug("registerServer");
config.api.modules.forEach(function(item) {
//console.log(item);
app.use('/' + config.api.route + "/" + item.route, require('./' + item.name));
serviceRegistry.register({
serviceId:config.server.id,
serviceHost:address(),
servicePort:config.server.port,
serviceProtocol:config.server.https.isEnabled ? "https" : "http",
endpointId:item.name,
endpointPath:config.api.route + "/" + item.route
}, function (err,item) {
if (err){
console.log(app.next())
debug(err);
}
});
});
}
};
var unregisterServer = function () {
if (!config.server.isCluster || cluster.worker.id===1){
debug("unregisterServer");
config.api.modules.forEach(function(item) {
serviceRegistry.unregister(config.server.id,item.name,function (err,item) {
if (err){
//TODO update flag inactive?
console.log(err);
}
if (!config.server.isCluster){
process.exit();
}
});
});
}
};
}
================================================
FILE: api-gateway-and-service-doscovery/service-login/Dockerbuild.sh
================================================
docker build -t micro-node-service-login:latest .
winpty docker run -it --rm -p 8081:8081 --name micro-node-service-login micro-node-service-login:latest
================================================
FILE: api-gateway-and-service-doscovery/service-login/Dockerfile
================================================
FROM node:6.2.0-onbuild
EXPOSE 8081
================================================
FILE: api-gateway-and-service-doscovery/service-login/config.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var fs = require('fs');
function Config() {
var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8');
return{
server:{
id:config.server.id,
port:config.server.port,
isCluster:config.server.isCluster,
https:config.server.https,
headers:config.server.headers,
httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null,
httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null,
},
api:{
route:config.api.route,
modules:config.api.modules
},
serviceRegistry:config.serviceRegistry
};
}
module.exports=Config;
================================================
FILE: api-gateway-and-service-doscovery/service-login/config.json
================================================
{
"server":{
"id":"ServiceLogin",
"port":8081,
"isCluster":true,
"https":{
"isEnabled":false,
"key":"",
"ca":""
},
"headers":[
{"name":"Access-Control-Allow-Origin","value":"*"},
{"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"},
{"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"}
]
},
"api":{
"route":"api",
"modules":[
{"name":"login", "route":"login"}
]
},
"serviceRegistry":{
"watchDog":{
"isEnabled":false,
"timer":30000
},
"database":{
"name":"my_mongo_db",
"user":"my_mongo_db_user",
"password":"my_mongo_db_password",
"host":"my_mongo_db_host",
"port":27017
}
}
}
================================================
FILE: api-gateway-and-service-doscovery/service-login/login.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var express = require('express'),
router = express.Router(),
debug = require('debug')('http'),
config= require ('./config')()
router.post('/', function (req, res,next) {
return res.status(200).send("## Login -> This is just a test response ;-)");
});
module.exports = router;
================================================
FILE: api-gateway-and-service-doscovery/service-login/package.json
================================================
{
"name": "MicroNodeService",
"version": "0.0.1",
"description": "Micro Node Tutorial",
"author": {
"name": "Domenico Vacchiano",
"email": "info@domenicovacchiano.com",
"url": "http://www.domenicovacchiano.com"
},
"homepage": "http://www.domenicovacchiano.com/",
"repository": {
"type": "git",
"url": ""
},
"engines": {
"node": ">= 0.6.0",
"npm": ">= 1.0.0"
},
"dependencies": {
"express": "^4.13.4",
"body-parser": "^1.15.1",
"request": "^2.72.0",
"morgan": "^1.7.0",
"network-address": "^1.1.0",
"micro-node-net-lib": "git@github.com:alchimya/micro-node-net-lib.git",
"micro-node-service-registry-lib": "git@github.com:alchimya/micro-node-service-registry-lib.git"
},
"private": true,
"scripts": {
"start": "node server.js"
},
"main": "server.js"
}
================================================
FILE: api-gateway-and-service-doscovery/service-login/server.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var config= require ('./config')(),
address = require('network-address'),
express=require('express'),
debug = require('debug')('http'),
bodyParser = require('body-parser'),
morgan= require('morgan'),
cluster = require('cluster'),
numCPUs = require('os').cpus().length,
netLib = require ('micro-node-net-lib'),
configServer= {
server:{
port:config.server.port
},
https:{
isEnabled:config.server.https.isEnabled,
key:config.server.httpsKeyContent,
ca:config.server.httpsCaContent
},
express:{
app:null
},
exitHandlers:["exit","SIGINT","SIGTERM"]
}
server = netLib.server(configServer),
serviceRegistry = require ('micro-node-service-registry-lib')({
name:config.serviceRegistry.database.name,
user:config.serviceRegistry.database.user,
password:config.serviceRegistry.database.password,
host:config.serviceRegistry.database.host,
port:config.serviceRegistry.database.port,
connectionPool:config.serviceRegistry.database.connectionPool
});
if (cluster.isMaster && config.server.isCluster) {
debug("cpus:" + numCPUs);
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log("cluster exit");
debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code);
cluster.fork();
});
} else {
var app=express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('dev'));
configServer.express.app = app;
//header(s) setting
app.all('/*', function(req, res, next) {
config.server.headers.forEach(function(item) {
//console.log(item);
res.header(item.name, item.value);
});
next();
});
//load API route(s)
config.api.modules.forEach(function(item) {
//console.log(item);
app.use('/' + config.api.route + "/" + item.route, require('./' + item.name));
});
server.create(function (err,server) {
if (!err){
//load API route(s) and register services
registerServer();
if (config.serviceRegistry.watchDog.isEnabled){
setInterval(function(){
registerServer();
}, config.serviceRegistry.watchDog.timer);
}
console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " +
config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : ""));
} else {
debug(err);
}
});
server.registerExitHandler(function () {
unregisterServer();
debug("Server Exit Handled");
});
var registerServer=function () {
if (!config.server.isCluster || cluster.worker.id===1){
debug("registerServer");
config.api.modules.forEach(function(item) {
//console.log(item);
app.use('/' + config.api.route + "/" + item.route, require('./' + item.name));
serviceRegistry.register({
serviceId:config.server.id,
serviceHost:address(),
servicePort:config.server.port,
serviceProtocol:config.server.https.isEnabled ? "https" : "http",
endpointId:item.name,
endpointPath:config.api.route + "/" + item.route
}, function (err,item) {
if (err){
console.log(app.next())
debug(err);
}
});
});
}
};
var unregisterServer = function () {
if (!config.server.isCluster || cluster.worker.id===1){
debug("unregisterServer");
config.api.modules.forEach(function(item) {
serviceRegistry.unregister(config.server.id,item.name,function (err,item) {
if (err){
//TODO update flag inactive?
console.log(err);
}
if (!config.server.isCluster){
process.exit();
}
});
});
}
};
}
================================================
FILE: api-gateway-and-service-doscovery/service-orders/Dockerbuild.sh
================================================
docker build -t micro-node-service-orders:latest .
winpty docker run -it --rm -p 8083:8083 --name micro-node-service-orders micro-node-service-orders:latest
================================================
FILE: api-gateway-and-service-doscovery/service-orders/Dockerfile
================================================
FROM node:6.2.0-onbuild
EXPOSE 8083
================================================
FILE: api-gateway-and-service-doscovery/service-orders/config.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var fs = require('fs');
function Config() {
var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8');
return{
server:{
id:config.server.id,
port:config.server.port,
isCluster:config.server.isCluster,
https:config.server.https,
headers:config.server.headers,
httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null,
httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null,
},
api:{
route:config.api.route,
modules:config.api.modules
},
serviceRegistry:config.serviceRegistry
};
}
module.exports=Config;
================================================
FILE: api-gateway-and-service-doscovery/service-orders/config.json
================================================
{
"server":{
"id":"ServiceOrders",
"port":8083,
"isCluster":true,
"https":{
"isEnabled":false,
"key":"",
"ca":""
},
"headers":[
{"name":"Access-Control-Allow-Origin","value":"*"},
{"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"},
{"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"}
]
},
"api":{
"route":"api",
"modules":[
{"name":"orders", "route":"orders"}
]
},
"serviceRegistry":{
"watchDog":{
"isEnabled":false,
"timer":30000
},
"database":{
"name":"my_mongo_db",
"user":"my_mongo_db_user",
"password":"my_mongo_db_password",
"host":"my_mongo_db_host",
"port":27017
}
}
}
================================================
FILE: api-gateway-and-service-doscovery/service-orders/orders.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var express = require('express'),
router = express.Router(),
debug = require('debug')('http'),
config= require ('./config')()
router.post('/', function (req, res,next) {
return res.status(200).send("## Orders -> This is just a test response ;-)");
});
module.exports = router;
================================================
FILE: api-gateway-and-service-doscovery/service-orders/package.json
================================================
{
"name": "MicroNodeService",
"version": "0.0.1",
"description": "Micro Node Tutorial",
"author": {
"name": "Domenico Vacchiano",
"email": "info@domenicovacchiano.com",
"url": "http://www.domenicovacchiano.com"
},
"homepage": "http://www.domenicovacchiano.com/",
"repository": {
"type": "git",
"url": ""
},
"engines": {
"node": ">= 0.6.0",
"npm": ">= 1.0.0"
},
"dependencies": {
"express": "^4.13.4",
"body-parser": "^1.15.1",
"request": "^2.72.0",
"morgan": "^1.7.0",
"network-address": "^1.1.0",
"micro-node-net-lib": "git@github.com:alchimya/micro-node-net-lib.git",
"micro-node-service-registry-lib": "git@github.com:alchimya/micro-node-service-registry-lib.git"
},
"private": true,
"scripts": {
"start": "node server.js"
},
"main": "server.js"
}
================================================
FILE: api-gateway-and-service-doscovery/service-orders/server.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var config= require ('./config')(),
address = require('network-address'),
express=require('express'),
debug = require('debug')('http'),
bodyParser = require('body-parser'),
morgan= require('morgan'),
cluster = require('cluster'),
numCPUs = require('os').cpus().length,
netLib = require ('micro-node-net-lib'),
configServer= {
server:{
port:config.server.port
},
https:{
isEnabled:config.server.https.isEnabled,
key:config.server.httpsKeyContent,
ca:config.server.httpsCaContent
},
express:{
app:null
},
exitHandlers:["exit","SIGINT","SIGTERM"]
}
server = netLib.server(configServer),
serviceRegistry = require ('micro-node-service-registry-lib')({
name:config.serviceRegistry.database.name,
user:config.serviceRegistry.database.user,
password:config.serviceRegistry.database.password,
host:config.serviceRegistry.database.host,
port:config.serviceRegistry.database.port,
connectionPool:config.serviceRegistry.database.connectionPool
});
if (cluster.isMaster && config.server.isCluster) {
debug("cpus:" + numCPUs);
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log("cluster exit");
debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code);
cluster.fork();
});
} else {
var app=express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('dev'));
configServer.express.app = app;
//header(s) setting
app.all('/*', function(req, res, next) {
config.server.headers.forEach(function(item) {
//console.log(item);
res.header(item.name, item.value);
});
next();
});
//load API route(s)
config.api.modules.forEach(function(item) {
//console.log(item);
app.use('/' + config.api.route + "/" + item.route, require('./' + item.name));
});
server.create(function (err,server) {
if (!err){
//load API route(s) and register services
registerServer();
if (config.serviceRegistry.watchDog.isEnabled){
setInterval(function(){
registerServer();
}, config.serviceRegistry.watchDog.timer);
}
console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " +
config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : ""));
} else {
debug(err);
}
});
server.registerExitHandler(function () {
unregisterServer();
debug("Server Exit Handled");
});
var registerServer=function () {
if (!config.server.isCluster || cluster.worker.id===1){
debug("registerServer");
config.api.modules.forEach(function(item) {
//console.log(item);
app.use('/' + config.api.route + "/" + item.route, require('./' + item.name));
serviceRegistry.register({
serviceId:config.server.id,
serviceHost:address(),
servicePort:config.server.port,
serviceProtocol:config.server.https.isEnabled ? "https" : "http",
endpointId:item.name,
endpointPath:config.api.route + "/" + item.route
}, function (err,item) {
if (err){
console.log(app.next())
debug(err);
}
});
});
}
};
var unregisterServer = function () {
if (!config.server.isCluster || cluster.worker.id===1){
debug("unregisterServer");
config.api.modules.forEach(function(item) {
serviceRegistry.unregister(config.server.id,item.name,function (err,item) {
if (err){
//TODO update flag inactive?
console.log(err);
}
if (!config.server.isCluster){
process.exit();
}
});
});
}
};
}
================================================
FILE: api-gateway-and-service-doscovery/service-signup/Dockerbuild.sh
================================================
docker build -t micro-node-service-signup:latest .
winpty docker run -it --rm -p 8082:8082 --name micro-node-service-signup micro-node-service-signup:latest
================================================
FILE: api-gateway-and-service-doscovery/service-signup/Dockerfile
================================================
FROM node:6.2.0-onbuild
EXPOSE 8082
================================================
FILE: api-gateway-and-service-doscovery/service-signup/config.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var fs = require('fs');
function Config() {
var config = JSON.parse(fs.readFileSync(__dirname + '/config.json'), 'utf8');
return{
server:{
id:config.server.id,
port:config.server.port,
isCluster:config.server.isCluster,
https:config.server.https,
headers:config.server.headers,
httpsKeyContent:config.server.https.key ? fs.readFileSync(__dirname + "/" + config.server.https.key) :null,
httpsCaContent:config.server.https.ca ? fs.readFileSync(__dirname + "/" + config.server.https.ca) :null,
},
api:{
route:config.api.route,
modules:config.api.modules
},
serviceRegistry:config.serviceRegistry
};
}
module.exports=Config;
================================================
FILE: api-gateway-and-service-doscovery/service-signup/config.json
================================================
{
"server":{
"id":"ServiceSignup",
"port":8082,
"isCluster":true,
"https":{
"isEnabled":false,
"key":"",
"ca":""
},
"headers":[
{"name":"Access-Control-Allow-Origin","value":"*"},
{"name":"Access-Control-Allow-Headers","value":"Origin, X-Requested-With, Content-Type, Accept"},
{"name":"Access-Control-Allow-Methods","value":"GET,PUT,POST,DELETE,OPTIONS"}
]
},
"api":{
"route":"api",
"modules":[
{"name":"signup", "route":"signup"}
]
},
"serviceRegistry":{
"watchDog":{
"isEnabled":false,
"timer":30000
},
"database":{
"name":"my_mongo_db",
"user":"my_mongo_db_user",
"password":"my_mongo_db_password",
"host":"my_mongo_db_host",
"port":27017
}
}
}
================================================
FILE: api-gateway-and-service-doscovery/service-signup/package.json
================================================
{
"name": "MicroNodeService",
"version": "0.0.1",
"description": "Micro Node Tutorial",
"author": {
"name": "Domenico Vacchiano",
"email": "info@domenicovacchiano.com",
"url": "http://www.domenicovacchiano.com"
},
"homepage": "http://www.domenicovacchiano.com/",
"repository": {
"type": "git",
"url": ""
},
"engines": {
"node": ">= 0.6.0",
"npm": ">= 1.0.0"
},
"dependencies": {
"express": "^4.13.4",
"body-parser": "^1.15.1",
"request": "^2.72.0",
"morgan": "^1.7.0",
"network-address": "^1.1.0",
"micro-node-net-lib": "git@github.com:alchimya/micro-node-net-lib.git",
"micro-node-service-registry-lib": "git@github.com:alchimya/micro-node-service-registry-lib.git"
},
"private": true,
"scripts": {
"start": "node server.js"
},
"main": "server.js"
}
================================================
FILE: api-gateway-and-service-doscovery/service-signup/server.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var config= require ('./config')(),
address = require('network-address'),
express=require('express'),
debug = require('debug')('http'),
bodyParser = require('body-parser'),
morgan= require('morgan'),
cluster = require('cluster'),
numCPUs = require('os').cpus().length,
netLib = require ('micro-node-net-lib'),
configServer= {
server:{
port:config.server.port
},
https:{
isEnabled:config.server.https.isEnabled,
key:config.server.httpsKeyContent,
ca:config.server.httpsCaContent
},
express:{
app:null
},
exitHandlers:["exit","SIGINT","SIGTERM"]
}
server = netLib.server(configServer),
serviceRegistry = require ('micro-node-service-registry-lib')({
name:config.serviceRegistry.database.name,
user:config.serviceRegistry.database.user,
password:config.serviceRegistry.database.password,
host:config.serviceRegistry.database.host,
port:config.serviceRegistry.database.port,
connectionPool:config.serviceRegistry.database.connectionPool
});
if (cluster.isMaster && config.server.isCluster) {
debug("cpus:" + numCPUs);
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log("cluster exit");
debug('Worker %d died with code/signal %s. Restarting worker...', worker.process.pid, signal || code);
cluster.fork();
});
} else {
var app=express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(morgan('dev'));
configServer.express.app = app;
//header(s) setting
app.all('/*', function(req, res, next) {
config.server.headers.forEach(function(item) {
//console.log(item);
res.header(item.name, item.value);
});
next();
});
//load API route(s)
config.api.modules.forEach(function(item) {
//console.log(item);
app.use('/' + config.api.route + "/" + item.route, require('./' + item.name));
});
server.create(function (err,server) {
if (!err){
//load API route(s) and register services
registerServer();
if (config.serviceRegistry.watchDog.isEnabled){
setInterval(function(){
registerServer();
}, config.serviceRegistry.watchDog.timer);
}
console.log("### " + config.server.id + " -> " + (config.server.https ? "HTTPS" : "HTTP") + " Server started on port " +
config.server.port + (config.server.isCluster ? " cluster worker " + cluster.worker.id : ""));
} else {
debug(err);
}
});
server.registerExitHandler(function () {
unregisterServer();
debug("Server Exit Handled");
});
var registerServer=function () {
if (!config.server.isCluster || cluster.worker.id===1){
debug("registerServer");
config.api.modules.forEach(function(item) {
//console.log(item);
app.use('/' + config.api.route + "/" + item.route, require('./' + item.name));
serviceRegistry.register({
serviceId:config.server.id,
serviceHost:address(),
servicePort:config.server.port,
serviceProtocol:config.server.https.isEnabled ? "https" : "http",
endpointId:item.name,
endpointPath:config.api.route + "/" + item.route
}, function (err,item) {
if (err){
console.log(app.next())
debug(err);
}
});
});
}
};
var unregisterServer = function () {
if (!config.server.isCluster || cluster.worker.id===1){
debug("unregisterServer");
config.api.modules.forEach(function(item) {
serviceRegistry.unregister(config.server.id,item.name,function (err,item) {
if (err){
//TODO update flag inactive?
console.log(err);
}
if (!config.server.isCluster){
process.exit();
}
});
});
}
};
}
================================================
FILE: api-gateway-and-service-doscovery/service-signup/signup.js
================================================
/**
* Created by domenicovacchiano on 07/07/16.
*/
var express = require('express'),
router = express.Router(),
debug = require('debug')('http'),
config= require ('./config')()
router.post('/', function (req, res,next) {
return res.status(200).send("## Signup -> This is just a test response ;-)");
});
module.exports = router;
================================================
FILE: dockerized-containers/.eslintrc.js
================================================
module.exports = {
"extends": "airbnb-base",
"rules": {
"comma-dangle": 0,
"no-console": 0,
"no-unused-vars" :0
}
};
================================================
FILE: dockerized-containers/.gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
/dist
.vscode
/test
/*/dist
# Runtime data
pids
*.pid
/node_modules
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
package-lock.json
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Jetbrains dir
.idea/
.DS_Store
# github dir
.github/
# .env files
bin/dev.env
bin/test.env
================================================
FILE: dockerized-containers/.travis.yml
================================================
language: node_js
sudo: false
node_js:
- 10
install:
- npm install
script:
- npm test
================================================
FILE: dockerized-containers/README.md
================================================
# Application for e-commerce Hub
REST API to support application features
- Express as web framework with Typescript
- Passport js for social authentication
- Express CORS enabled
- boom for error codes & Joi for Validation
- Winston for logging and express minitor for monitoring
- Mongoose as ODM driver
- eslint validation extending airbnb styleguide
- git hooks & CI/CD in place
- Typescript based compilation tsc compiler
- TDD in progress with Mocha
- JWT based authentication
- multiple Mongoose collection with referencing
- payment gateway Integration
- Heroku deployment
- Mini e-commerce platform
# Cart Application #
"It's just simple application to provide REST APIs for mini e-commerce platform where individual can buy products and can pay the bills
- microservices architecture
- Client application in React
- User Auth microservices
- Cart services
- Admin Microservices


```
# Application Execution
```javascript
git clone repo
npm install
npm run startdev
tsc -- watch
```
# Application configuration
```javascript
env.sh need to be added locally
export NODE_ENV="dev"
export PORT="3005"
export MONGOURL="mongodb://mongo/hello"
export EXPRESS_SESSION_SECRET="************************"
export F_CLIENTID="**************"
export F_CLIENTSECRET="**********************"
```
# update etc/hosts file
```
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
127.0.0.1 mysql redis mongo
127.0.0.1 ms-commerce.com
```
# Sevices end-point
- http://ms-commerce.com/api/v1 Auth services
- http://ms-commerce.com/admin/v1 Admin APIs
- http://ms-commerce.com/admin/v1 Cart APIs
# Application NPM Script
```javascript
"start": "cd dist && nodemon server.js",
"prestart": "tsc && cp -r uploads dist/ && cp -r app/global dist/app/",
"clean" : "rm -rf dist",
"copy" : "cp -r uploads dist/ && cp -r app/global dist/app/"
```
================================================
FILE: dockerized-containers/docker-compose.yml
================================================
version: '3.5'
services:
gateway:
image: nginx:1.11
ports:
- 80:80
- 443:443
volumes:
- ./proxy/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./proxy/ssl:/etc/nginx/ssl:ro
depends_on:
- ms_commerce_auth
- ms_commerce_admin
- ms_commerce_client
networks:
- ms_network
ms_mysql:
container_name: ms_mysql
image: mysql:5.7
volumes:
- ~/datadir/mysql:/var/lib/mysql
ports:
- 3306:3306
- 33060:33060
environment:
MYSQL_ROOT_PASSWORD: root
networks:
- ms_network
ms_commerce_mongo:
image: mongo
container_name: ms_commerce_mongo
restart: unless-stopped
volumes:
- ~/datadir/mongo:/data/db
ports:
- 27017:27017
networks:
- ms_network
ms_commerce_auth:
container_name: ms_commerce_auth
build: ./e-Commerce-Auth/
image: e-commerce-auth
volumes:
- ./e-Commerce-Auth/:/usr/src/app
- /usr/src/app/node_modules
ports:
- 3001:3001
- 9201:9201
depends_on:
- ms_mysql
networks:
- ms_network
ms_commerce_cart:
container_name: ms_commerce_cart
build: ./e-Commerce-Cart/
image: e-commerce-cart
volumes:
- ./e-Commerce-Cart/:/usr/src/app
- /usr/src/app/node_modules
ports:
- 3004:3004
- 9204:9204
depends_on:
- ms_mysql
networks:
- ms_network
ms_commerce_admin:
build: ./e-Commerce-Admin/
image: e-commerce-admin
container_name: ms_commerce_admin
environment:
- NODE_ENV=local
volumes:
- ./e-Commerce-Admin/:/usr/src/app
- /usr/src/app/node_modules
ports:
- 3002:3002
- 9202:9202
depends_on:
- ms_commerce_mongo
networks:
- ms_network
ms_commerce_client:
build: ./e-Commerce-Client/
image: e-commerce-client
container_name: ms_commerce_client
environment:
- NODE_ENV=local
volumes:
- ./e-Commerce-Client/:/usr/src/app
- /usr/src/app/node_modules
ports:
- 3003:3003
depends_on:
- ms_commerce_admin
- ms_commerce_auth
networks:
- ms_network
networks:
ms_network:
driver: bridge
name: ms_network
================================================
FILE: dockerized-containers/e-Commerce-Admin/Dockerfile
================================================
FROM node:carbon
# Create app directory
WORKDIR /usr/src/app
# Bundle app source
COPY . .
# npm install
RUN npm install
# Run npm install --global grpc --unsafe-perm
EXPOSE 3002 9202
CMD [ "npm", "run", "watchserver" ]
CMD [ "npm", "run", "startdev" ]
================================================
FILE: dockerized-containers/e-Commerce-Admin/README.md
================================================
# Application for e-commerce Hub
REST API to support application features
- Express as web framework with Typescript
- Passport js for social authentication
- Express CORS enabled
- boom for error codes & Joi for Validation
- Winston for logging and express minitor for monitoring
- Mongoose as ODM driver
- eslint validation extending airbnb styleguide
- git hooks & CI/CD in place
- Typescript based compilation tsc compiler
- TDD in progress with Mocha
- JWT based authentication
- multiple Mongoose collection with referencing
- payment gateway Integration
- Heroku deployment
- Mini e-commerce platform
# Cart Application #
"It's just simple application to provide REST APIs for mini e-commerce platform where individual can buy products and can pay the bills
```
# Application Execution
```javascript
git clone repo
npm install
npm run startdev
tsc -- watch
```
# Application configuration
```javascript
env.sh need to be added locally
export NODE_ENV="dev"
export PORT="3005"
export MONGOURL="mongodb://mongo/hello"
export EXPRESS_SESSION_SECRET="************************"
export F_CLIENTID="**************"
export F_CLIENTSECRET="**********************"
```
# Application NPM Script
```javascript
"start": "cd dist && nodemon server.js",
"prestart": "tsc && cp -r uploads dist/ && cp -r app/global dist/app/",
"clean" : "rm -rf dist",
"copy" : "cp -r uploads dist/ && cp -r app/global dist/app/"
```
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/config/email.ts
================================================
'use strict';
export default {
global: {
from: 'info@kpilibrary.com',
},
welcome: {
subject: 'Welcome to KPI Library',
},
password_reset: {
subject: 'KPI Library: Reset your password',
},
event_booked_guest: {
subject: 'KPI Library: Your Booking Has Been Confirmed',
},
event_booked_host: {
subject: 'KPI Library: Your Event Has Been Booked',
},
event_booked_guests_notification: {
subject: 'KPI Library: Your Booking Has Been Confirmed',
},
message_received: {
subject: 'KPI Library: New Message Received',
},
guest_review_email: {
subject: 'KPI Library: Event Completed',
},
alacarte_booked_guest: {
subject: 'KPI Library: Alacarte Booking Details',
},
alacarte_booked_host: {
subject: 'KPI Library: Your Alacarte Has Been Booked',
}
}
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/config/environments/dev.ts
================================================
/* eslint quote-props: 0 */
export { }
const configuration: any = {};
configuration.mongo = {
url: process.env.MONGODB_URI || process.env.MONGOURL,
};
configuration.URL = {
frontEnd: process.env.FE_URL
}
configuration.facebook = {
client_id: process.env.F_CLIENTID,
client_secret: process.env.F_CLIENTSECRET,
callback_url: process.env.F_CALLBACK
};
configuration.google = {
client_id: process.env.G_CLIENTID,
client_secret: process.env.G_CLIENTSECRET,
callback_url: process.env.G_CALLBACK
};
configuration.linkedin = {
client_id: process.env.L_CLIENTID,
client_secret: process.env.L_CLIENTSECRET,
callback_url: process.env.L_CALLBACK
};
configuration.twitter = {
client_id: process.env.T_CLIENTID,
client_secret: process.env.T_CLIENTSECRET,
callback_url: process.env.T_CALLBACK
};
configuration.email = {
apiKey: process.env.API_KEY,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
}
}
configuration.twilio = {
sid: process.env.SID,
token: process.env.TOKEN,
phone: process.env.PHONE,
}
configuration.url = {
FE: process.env.FE,
API: process.env.API,
}
configuration.uploadpath = {
uploaddir: process.env.UPLOAD_DIR,
profiledir: process.env.PROFILE_PICTURE_DIR
}
module.exports = configuration;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/config/environments/qa.ts
================================================
/* eslint quote-props: 0 */
export { }
const configuration: any = {};
configuration.mongo = {
url: process.env.MONGODB_URI || process.env.MONGOURL,
};
configuration.URL = {
frontEnd: process.env.FE_URL
}
configuration.facebook = {
client_id: process.env.F_CLIENTID,
client_secret: process.env.F_CLIENTSECRET,
callback_url: process.env.F_CALLBACK
};
configuration.google = {
client_id: process.env.G_CLIENTID,
client_secret: process.env.G_CLIENTSECRET,
callback_url: process.env.G_CALLBACK
};
configuration.linkedin = {
client_id: process.env.L_CLIENTID,
client_secret: process.env.L_CLIENTSECRET,
callback_url: process.env.L_CALLBACK
};
configuration.twitter = {
client_id: process.env.T_CLIENTID,
client_secret: process.env.T_CLIENTSECRET,
callback_url: process.env.T_CALLBACK
};
configuration.email = {
apiKey: process.env.API_KEY,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
}
}
configuration.twilio = {
sid: process.env.SID,
token: process.env.TOKEN,
phone: process.env.PHONE,
}
configuration.url = {
FE: process.env.FE,
API: process.env.API,
}
configuration.uploadpath = {
uploaddir: process.env.UPLOAD_DIR,
profiledir: process.env.PROFILE_PICTURE_DIR
}
module.exports = configuration;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/config/environments/test.ts
================================================
/* eslint quote-props: 0 */
export { }
const configuration: any = {};
configuration.mongo = {
url: process.env.MONGODB_URI || process.env.MONGOURL,
};
configuration.URL = {
frontEnd: process.env.FE_URL
}
configuration.facebook = {
client_id: process.env.F_CLIENTID,
client_secret: process.env.F_CLIENTSECRET,
callback_url: process.env.F_CALLBACK
};
configuration.google = {
client_id: process.env.G_CLIENTID,
client_secret: process.env.G_CLIENTSECRET,
callback_url: process.env.G_CALLBACK
};
configuration.linkedin = {
client_id: process.env.L_CLIENTID,
client_secret: process.env.L_CLIENTSECRET,
callback_url: process.env.L_CALLBACK
};
configuration.twitter = {
client_id: process.env.T_CLIENTID,
client_secret: process.env.T_CLIENTSECRET,
callback_url: process.env.T_CALLBACK
};
configuration.email = {
apiKey: process.env.API_KEY,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
}
}
configuration.twilio = {
sid: process.env.SID,
token: process.env.TOKEN,
phone: process.env.PHONE,
}
configuration.url = {
FE: process.env.FE,
API: process.env.API,
}
configuration.uploadpath = {
uploaddir: process.env.UPLOAD_DIR,
profiledir: process.env.PROFILE_PICTURE_DIR
}
module.exports = configuration;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/controller/UserController.ts
================================================
export { };
const uuidv4 = require('uuid/v4');
import User from '../models/user';
declare function require(name: string);
import Helper from '../helper/bcrypt';
const jwt = require('jsonwebtoken');
import helper from '../helper/bcrypt';
import mailEvents from '../events/notification';
import logger from '../helper/logger';
import email from '../helper/email';
const saltRounds = 10;
class userController {
static getUserByEmail(email, cb) {
User.findOne({ 'email': email }, (error, user) => {
if (user) {
cb(null, user);
} else {
cb('User does not exist in system', null);
}
});
}
static validateUser(req, res, cb) {
const { body } = req;
User.find({ email: body.email })
.then((data) => {
if (data && data.length) {
const flag = helper.comparePassword(body.password, data[0].password)
if (flag) {
jwt.sign(helper.buildUserToken(data[0]), 'secretkey', (tokError, token) => {
cb(null, token);
});
} else {
cb(new Error('username password does not match'), null);
}
}
else {
cb(new Error('no user found with this account email'), null);
}
});
}
static registerDefault(req, res, cb) {
const { body } = req;
const { location } = req;
const hash = helper.generateSaltValue(body.password);
return User.find({ email: body.email }).then((user) => {
if (user && user.length > 0) {
cb(new Error('user already regitsered with us'), null);
} else {
return User.create(this.buildUser(body, hash, location)
, (error, user) => {
if (error) {
cb(error, null);
} else {
logger.info('emitting user create event');
mailEvents.emit("welcome", user);
cb(null, user);
}
});
}
});
}
static buildUser(body, hash = null, location = null) {
const build = {
username: body.username,
phone: body.phone,
email: body.email,
email_verified: false,
phone_verified: false,
picture: body.picture ? body.picture : null,
status: 1,
gender: null,
documents: [],
type: 1,
social: body.meta,
uuid: uuidv4()
}
return hash ? Object.assign({}, build, { password: hash }) : build;
}
static registerSocial(user, callback) {
User.findOne({ email: user.email }, (error, existingUser) => {
if (existingUser) {
callback(null, (existingUser));
} else {
User.create(this.buildUser(user, null), (err, user) => {
if (err) {
callback(err, null);
} else {
callback(null, user);
mailEvents.emit("welcome", user);
}
});
}
});
}
static activateUserAccount(uuid, cb) {
User.findOne({ 'uuid': uuid }, (error, foundUser) => {
if (foundUser) {
foundUser.email_verified = true;
foundUser.save(function (err) {
if (err) {
cb('error occoured while updating record');
} else {
cb(null, 'done');
}
});
} else {
cb('User does not exist in system');
}
});
}
static resetPassword(email, callback) {
// just generate password and send new password on mail
User.findOne({ 'email': email }, (error, foundUser) => {
if (foundUser) {
let password = Math.random().toString(36).slice(2);
const hash = helper.generateSaltValue(password);
foundUser.password = hash;
foundUser.save(function (err) {
if (err) {
callback('error occoured while updating record');
} else {
mailEvents.emit("forgotPassword", foundUser, password);
callback(null, 'done');
}
});
} else {
callback('User does not exist in system with this email');
}
});
}
static changeUserRole(req, callback) {
const email = req.params.email
const body = req.body
User.findOne({ 'email': email }, (error, user) => {
if (user) {
user.type = 2;
user.save(function (err, updated_user) {
if (err) {
callback('error occoured while chaging role');
} else {
callback(null, updated_user);
}
});
}
else {
callback('user not found in system', null);
}
});
}
static updateUser(email, data, callback) {
User.findOne({ 'email': email }, (error, user) => {
if (user) {
if (data.username) { user.username = data.username; }
if (data.gender) { user.gender = data.gender; }
if (data.phone) { user.phone = data.phone; }
if (data.profile_picture) { user.profile_picture = data.profile_picture; }
if (data.password && data.password === data.confirm_password) {
const hash = helper.generateSaltValue(data.password);
user.password = hash;
}
if ( data.picture ) { user.picture = Helper.avatarURL(data.picture) }
if (data.phone_verified) {
user.phone_verified = true;
}
if (data.document) {
user.documents.push(data.document);
}
if (data.meta) {
user.meta = {
about: data.meta.about || '',
fun_fact: data.meta.fun_fact || '',
payment: data.meta.payment || '',
}
}
user.save(function (err, updated_user) {
if (err) {
callback('error occoured while updating record');
} else {
callback(null, updated_user);
}
});
} else {
callback('user not found', null);
}
});
}
}
export default userController;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/events/notification.ts
================================================
import Email from '../helper/email';
declare function require(name: string);
const events = require('events');
const winston = require('winston');
// import Twillo from '../helper/twillo';
const eventEmitter = new events.EventEmitter();
eventEmitter.on('welcome', (user) => {
winston.log('info', `sending welcome email to ${user.email}`);
// Twillo.default_notification(user.phone, 'welcome')
Email.welcome(user);
});
eventEmitter.on('forgotPassword', (user, password, uuid) => {
winston.log('info', `sending forgotPassword email to ${user.email}`);
Email.password_reset(user, password);
// Twillo.default_notification(user.phone, 'welcome')
});
export default eventEmitter;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/global/templates/emails/password-reset-email/html.pug
================================================
html(lang='en')
head
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1, shrink-to-fit=no')
title password has successfully been reset
link(href='https://fonts.googleapis.com/css?family=Rubik:300,300i,400,400i,500,500i,700,700i,900,900i', rel='stylesheet')
link(rel='shortcut icon', type='image/x-icon', href='images/favicon.ico')
link(rel='stylesheet', href='../assets/styles/style.css', type='text/css')
body(data-gr-c-s-loaded='true', style='')
.template-wrapper
table.body(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
td.container
.content
table.main
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
a.template-logo(href='../index.html')
img(src='https://kekasrijan.herokuapp.com/static/media/kpi.88a7c7c4.png', alt='')
p.lead
| Hello #{user.email},
br
| Your password has successfully been reset
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td.mt30.mb30(align='center')
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
p.user-text
span Your new password is #[pre #{password}]
br
a.btn-primary(href= login_url) Login
p Thank you
p.mb0
| If you have any problems, please contact me at
a.click-link(href='#') admin@gmail.com
table.help-section
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
h2.text-center.mb0 Need more help?
a.support-link(href='#') We're here,ready to here
table
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
p
| You received this email beacuse you just signed up for new account. If it look weird
a.default-link(href='#') view it in your browser
.footer
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td.content-block
p.text-center
| © 2018 KPI App, Goa India
br
| If these emails get annoying, please feel to
a(href='#') unsubscribe
td
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/global/templates/emails/password-reset-email/style.css
================================================
@charset "UTF-8";
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
.container {
display: block;
Margin: 0 auto !important;
max-width: 580px;
padding: 10px;
width: 580px;
position: relative;
bottom: 140px;
}
img {
border: none;
-ms-interpolation-mode: bicubic;
max-width: 100%;
}
body {
background-color: #f6f6f6;
font-family: 'Rubik', sans-serif;
font-size: 15px;
line-height: 28px;
-webkit-font-smoothing: antialiased;
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
}
table td {
font-family: sans-serif;
font-size: 14px;
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
.body {
background-color: #f6f6f6;
width: 100%;
}
.lead {
font-size: 18px;
}
.mt30 {
margin-top: 30px;
display: block;
}
.mb30 {
margin-bottom: 30px;
display: block;
}
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
.container {
display: block;
Margin: 0 auto !important;
/* makes it centered */
max-width: 580px;
padding: 10px;
width: 580px;
position: relative;
bottom: 140px;
}
/* This should also be a block element, so that it will fill 100% of the .container */
.content {
box-sizing: border-box;
display: block;
Margin: 0 auto;
max-width: 580px;
padding: 10px;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.template-wrapper {
background-color: #03A9F4;
width: 100%;
height: 250px;
position: relative;
}
.click-link {
color: #03A9F4;
display: inline-block;
margin-bottom: 20px;
}
.help-section {
background-color: #ffdcdc;
border-radius: 3px;
width: 100%;
text-align: center;
}
.mb0 {
margin-bottom: 0px;
}
.support-link {
color: #03A9F4;
display: inline-block;
font-size: 19px;
margin-bottom: 0px;
}
.template-logo {
display: block;
margin-bottom: 40px;
margin: auto;
}
.user-text {
font-size: 18px;
font-weight: 500;
}
.user-text span {
font-weight: 600;
}
.text-secondary {
color: #218ef4 !important
}
.main {
background: #ffffff;
border-radius: 3px;
width: 100%;
margin-bottom: 20px;
}
.wrapper {
box-sizing: border-box;
padding: 40px 25px;
}
.content-block {
padding-bottom: 10px;
padding-top: 10px;
line-height: 2;
}
.footer {
clear: both;
text-align: center;
width: 100%;
}
.footer td, .footer p, .footer span, .footer a {
color: #999999;
font-size: 12px;
text-align: center;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1, h2, h3, h4 {
color: #000000;
font-family: sans-serif;
font-weight: 400;
line-height: 1.4;
margin: 0;
Margin-bottom: 30px;
}
h1 {
font-size: 35px;
font-weight: 300;
text-align: center;
text-transform: capitalize;
}
p, ul, ol {
font-family: sans-serif;
font-size: 15px;
font-weight: normal;
margin: 0;
margin-bottom: 15px;
}
p li, ul li, ol li {
list-style-position: inside;
margin-left: 5px;
}
a {
color: #3498db;
text-decoration: underline;
}
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
width: 100%;
}
.btn>tbody>tr>td {
padding-bottom: 15px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 5px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 1px #3498db;
border-radius: 5px;
box-sizing: border-box;
color: #3498db;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 12px 25px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background-color: #3498db;
}
.btn-primary a {
background-color: #03A9F4;
border-color: #03A9F4;
color: #ffffff;
}
.default-link {
color: #03A9F4;
}
.default-link:hover {
color: #03A9F4;
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
hr {
border: 0;
border-bottom: 1px solid #f6f6f6;
Margin: 20px 0;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class=body] p, table[class=body] ul, table[class=body] ol, table[class=body] td, table[class=body] span, table[class=body] a {
font-size: 16px !important;
}
table[class=body] .wrapper, table[class=body] .article {
padding: 10px !important;
}
table[class=body] .content {
padding: 0 !important;
}
table[class=body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=body] .btn table {
width: 100% !important;
}
table[class=body] .btn a {
width: 100% !important;
}
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
.btn-primary table td:hover {
background-color: #34495e !important;
}
.btn-primary a:hover {
background-color: #03A9F4 !important;
border-color: #03A9F4 !important;
}
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #03A9F4;
border: solid #03A9F4;
border-width: 6px 18px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 28px;*/
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
border-radius: 4px;
text-transform: capitalize;
}
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/global/templates/emails/welcome-email/html.pug
================================================
html(lang='en')
head
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1, shrink-to-fit=no')
title Account Activation email || KPI Library
link(href='https://fonts.googleapis.com/css?family=Rubik:300,300i,400,400i,500,500i,700,700i,900,900i', rel='stylesheet')
link(rel='shortcut icon', type='image/x-icon', href='images/favicon.ico')
link(rel='stylesheet', href='../assets/styles/style.css', type='text/css')
body(data-gr-c-s-loaded='true', style='')
.template-wrapper
table.body(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
td.container
.content
table.main
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
a.template-logo(href='../index.html')
img(src='https://kekasrijan.herokuapp.com/static/media/kpi.88a7c7c4.png', alt='')
p.lead
| Hello KPI Library,
br
| Thanks for Signup on KPI App
br
| We have sent User Account Activation Link below
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td.mt30.mb30(align='center')
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
p.user-text
| Hi,
span #{user.email},
br
br
a.btn-primary(href= activate_url) Activate your Account
p Thank you
p.mb0
| If you have any problems, please contact me at
a.click-link(href='#') admin@gmail.com
table.help-section
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
h2.text-center.mb0 Need more help?
a.support-link(href='#') We're here,ready to here
table
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
p
| You received this email beacuse you just signed up for new account. If it look weird
a.default-link(href='#') view it in your browser
.footer
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td.content-block
p.text-center
| © 2018 KPI App, Goa India
br
| If these emails get annoying, please feel to
a(href='#') unsubscribe
td
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/global/templates/emails/welcome-email/style.css
================================================
@charset "UTF-8";
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
.container {
display: block;
Margin: 0 auto !important;
max-width: 580px;
padding: 10px;
width: 580px;
position: relative;
bottom: 140px;
}
img {
border: none;
-ms-interpolation-mode: bicubic;
max-width: 100%;
}
body {
background-color: #f6f6f6;
font-family: 'Rubik', sans-serif;
font-size: 15px;
line-height: 28px;
-webkit-font-smoothing: antialiased;
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
}
table td {
font-family: sans-serif;
font-size: 14px;
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
.body {
background-color: #f6f6f6;
width: 100%;
}
.lead {
font-size: 18px;
}
.mt30 {
margin-top: 30px;
display: block;
}
.mb30 {
margin-bottom: 30px;
display: block;
}
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
.container {
display: block;
Margin: 0 auto !important;
/* makes it centered */
max-width: 580px;
padding: 10px;
width: 580px;
position: relative;
bottom: 140px;
}
/* This should also be a block element, so that it will fill 100% of the .container */
.content {
box-sizing: border-box;
display: block;
Margin: 0 auto;
max-width: 580px;
padding: 10px;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.template-wrapper {
background-color: #03A9F4;
width: 100%;
height: 250px;
position: relative;
}
.click-link {
color: #03A9F4;
display: inline-block;
margin-bottom: 20px;
}
.help-section {
background-color: #ffdcdc;
border-radius: 3px;
width: 100%;
text-align: center;
}
.mb0 {
margin-bottom: 0px;
}
.support-link {
color: #03A9F4;
display: inline-block;
font-size: 19px;
margin-bottom: 0px;
}
.template-logo {
display: block;
margin-bottom: 40px;
margin: auto;
}
.user-text {
font-size: 18px;
font-weight: 500;
}
.user-text span {
font-weight: 600;
}
.text-secondary {
color: #218ef4 !important
}
.main {
background: #ffffff;
border-radius: 3px;
width: 100%;
margin-bottom: 20px;
}
.wrapper {
box-sizing: border-box;
padding: 40px 25px;
}
.content-block {
padding-bottom: 10px;
padding-top: 10px;
line-height: 2;
}
.footer {
clear: both;
text-align: center;
width: 100%;
}
.footer td, .footer p, .footer span, .footer a {
color: #999999;
font-size: 12px;
text-align: center;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1, h2, h3, h4 {
color: #000000;
font-family: sans-serif;
font-weight: 400;
line-height: 1.4;
margin: 0;
Margin-bottom: 30px;
}
h1 {
font-size: 35px;
font-weight: 300;
text-align: center;
text-transform: capitalize;
}
p, ul, ol {
font-family: sans-serif;
font-size: 15px;
font-weight: normal;
margin: 0;
margin-bottom: 15px;
}
p li, ul li, ol li {
list-style-position: inside;
margin-left: 5px;
}
a {
color: #3498db;
text-decoration: underline;
}
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
width: 100%;
}
.btn>tbody>tr>td {
padding-bottom: 15px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 5px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 1px #3498db;
border-radius: 5px;
box-sizing: border-box;
color: #3498db;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 12px 25px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background-color: #3498db;
}
.btn-primary a {
background-color: #3498db;
border-color: #3498db;
color: #ffffff;
}
.default-link {
color: #3498db;
}
.default-link:hover {
color: #3498db;
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
hr {
border: 0;
border-bottom: 1px solid #f6f6f6;
Margin: 20px 0;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class=body] p, table[class=body] ul, table[class=body] ol, table[class=body] td, table[class=body] span, table[class=body] a {
font-size: 16px !important;
}
table[class=body] .wrapper, table[class=body] .article {
padding: 10px !important;
}
table[class=body] .content {
padding: 0 !important;
}
table[class=body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=body] .btn table {
width: 100% !important;
}
table[class=body] .btn a {
width: 100% !important;
}
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
.btn-primary table td:hover {
background-color: #34495e !important;
}
.btn-primary a:hover {
background-color: #03A9F4 !important;
border-color: #03A9F4 !important;
}
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #03A9F4;
border: solid #03A9F4;
border-width: 6px 18px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 28px;*/
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
border-radius: 4px;
text-transform: capitalize;
}
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/global/templates/response/index.ts
================================================
class ResponseTemplate {
static general(data) {
return data;
}
static error(code, message, description) {
return {
statusCode: code || 400,
message: message || 'some error occoured',
description: description || 'error occoured on server, please try again after some time.'
};
}
static authError() {
return this.error(
403,
'authentication error',
'no authentication token provided, please login first and provide the authentication token.'
);
}
static invalidAuthError() {
return this.error(
403,
'authentication error',
'invalid Token provided, please login first and provide the authentication token.'
);
}
static emptyContent() {
return this.general({
statusCode: 402,
message: 'empty content found',
description: 'you must provide valid data and it must not be empty.',
helpful_links: ['http://stackoverflow.com/questions/18419428/what-is-the-minimum-valid-json']
});
}
static invalidContentType() {
return this.general({
statusCode: 400,
message: 'invalid content type',
description: 'you must specify content type and it must be application/json',
helpful_links: ['http://stackoverflow.com/questions/477816/what-is-the-correct-json-content-type']
});
}
static routeNotFound() {
return this.error(
405,
'resource not found',
'the resource your tried to access doesn\'t exist or you dont have permissions to access it.'
);
}
static userNotFound() {
return this.error(
400,
'user not found',
"the user you're looking for doesn't exist or you dont have permissions to access it."
);
}
static updateErrorOccoured(error) {
return this.error(
301,
'error occoured',
error || 'error occoured while updating your data.'
);
}
static success(description, data=null) {
return {
statusCode: 200,
message: 'success',
description: description || 'data successfully saved.',
...data
}
}
}
export default ResponseTemplate;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/helper/bcrypt.ts
================================================
const bcrypt = require('bcrypt-nodejs');
const jwt = require('jsonwebtoken');
const {url} = global['configuration']
const {uploadpath} = global['configuration']
const path = require('path');
const fs = require('fs');
const helper = {
generateSaltValue(password) {
const salt = bcrypt.genSaltSync(); // enter number of rounds, default: 10
const hash = bcrypt.hashSync(password, salt);
return hash;
},
comparePassword(userPassword, password ) {
if (!userPassword.length || !( password && password.length > 0) ) {
return false;
}
return bcrypt.compareSync(userPassword, password);
},
authRedirectUrl( path ) {
return `${url.FE}/#/auth/validate-token/${path}`;
},
buildUserToken(data) {
return {
email: data.email,
id:data._id,
username: data.username ? data.username : data.email,
hasPassword: data.password ? true : false,
type : data.type || 1,
picture : data.picture
}
},
resource( path ) {
return `${url.API}${path}`;
},
getFileExtension( file ) {
let extensions = file.split('.');
if ( extensions.length === 1 ) {
return 'jpg';
} else {
return extensions.pop();
}
},
avatarURL( filename ) {
if ( filename.includes('://') ) {
return filename;
}
return this.resource(`/${uploadpath.uploaddir}/${uploadpath.profiledir}/${filename}`);
},
userDocumentURL( filename ) {
if ( filename.includes('://') ) {
return filename;
}
return this.resource(`/${uploadpath.uploaddir}/${uploadpath.documentdir}/${filename}`);
},
randomString() {
return Math.random().toString(36).substring(2, 7);
},
deleteFile( type, filename ) {
let location;
if ( type === 'profile' ) { location = path.join( uploadpath.uploaddir, uploadpath.profiledir ) }
else { location = uploadpath.uploaddir; }
if (filename) {
fs.unlink( path.join( location, filename ), () => {
// in case we need to perform additional operations.
});
}
},
getPaymentMethodName( method ) {
if ( method == 1 ) { return 'PayPal'; }
else if ( method == 2 ) { return 'PayPal'; }
else if ( method == 3 ) { return 'Instamojo'; }
else { return 'Not Specified'; }
},
getCurrency(currency) {
let allCurrency = {
1: 'USD',
2: 'INR',
};
if( allCurrency[currency] ) {
return allCurrency[currency];
} else {
return allCurrency[1];
}
},
verificationCode() {
let code = Math.floor((Math.random()*999999)+111111);
return code;
}
};
export default helper;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/helper/email.ts
================================================
const path = require('path');
declare function require(name:string);
const nodemailer = require('nodemailer');
const url = global['configuration'].url;
const mailConfig = global['configuration'].email;
import emailConfig from '../config/email';
import { EmailTemplate } from 'email-templates';
// const Twillo = require('./twillo');
const transport = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
// type: 'OAuth2',
user: mailConfig.auth.user,
pass: mailConfig.auth.pass
},
});
const Email = {
welcome(user) {
if (user.email) {
let templateDir = path.join('app/global/templates', 'emails', 'welcome-email');
let welcomeEmail = new EmailTemplate(templateDir);
welcomeEmail.render({ user: user, activate_url: `${url.API}/auth/activate/${user.uuid}` }, (err, result) => {
transport.sendMail(
{
from: emailConfig.global.from,
to: user.email,
subject: emailConfig.welcome.subject,
html: result.html,
}, (err, info) => {
// some error occoured...
console.log(err);
}
);
});
}
},
password_reset(user, password) {
if (user.email) {
let templateDir = path.join('app/global/templates', 'emails', 'password-reset-email');
let passwordResetEmail = new EmailTemplate(templateDir);
passwordResetEmail.render({ user: user, login_url: `${url.FE}/#/auth/login`, password: password }, (err, result) => {
transport.sendMail(
{
from: emailConfig.global.from,
to: user.email,
subject: emailConfig.password_reset.subject,
html: result.html,
}, (err, info) => {
// some error occoured...
}
);
});
}
if (user.phone_verified) {
// Twillo.password_reset_notification(user.phone);
}
},
};
export default Email;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/helper/errorHandler.ts
================================================
import * as winston from 'winston';
import ResponseTemplate from './responseTemplate';
/* eslint class-methods-use-this:0 */
const env = process.env.NODE_ENV;
const onDevEnv = env === 'dev' || env === 'test' || env === 'local';
class errorHandler {
public internalServerError(err, req, res, next) {
winston.log('info',err);
if (err.isBoom) {
// Error From joi express validator
const error = {
message: err.output.payload.error,
error: err.output.payload.message
};
res.status(400).json(ResponseTemplate.BadRequestFromJoi(error));
} else { // internalServerError
res.status(500).json({
success: false,
message: err.message,
error: (onDevEnv) ? err.stack : {}
});
}
}
public PageNotFound(req, res, err) {
res.status(404).json({ message: 'api not found' });
}
}
export default new errorHandler();
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/helper/logger.ts
================================================
const winston = require('winston');
// define the custom settings for each transport (file, console)
const options = {
console: {
level: 'info',
handleExceptions: true,
json: true,
colorize: true,
prettyPrint: true,
humanReadableUnhandledException: true
}
};
const logger = new winston.Logger({
transports: [
// new winston.transports.File(options.file),
new winston
.transports
.Console(options.console),
],
exceptionHandlers: [
// new winston.transports.File(options.errorLog)
],
exitOnError: false, // do not exit on handled exceptions
});
// create a stream object with a 'write' function that will be used by `morgan`
logger.stream = {
write(message, encoding) {
logger.info(message);
}
};
export default logger;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/helper/responseTemplate.ts
================================================
/* istanbul ignore file */
const data: any = {
general(data) {
return data;
},
successMessage(message) {
return {
success: true,
message
};
},
success(data, message) {
return {
success: true,
message,
data
};
},
error(message, err, code= null) {
return {
success: false,
message: message || 'some error occurred',
error: err || 'error occurred on server, please try again after some time.'
};
},
emptyContent() {
return this.general({
message: 'empty content found',
description: 'you must provide valid data and it must not be empty.',
helpful_links: ['http://stackoverflow.com/questions/18419428/what-is-the-minimum-valid-json']
});
},
invalidContentType() {
return this.general({
message: 'invalid content type',
description: 'you must specify content type and it must be application/json',
helpful_links: ['http://stackoverflow.com/questions/477816/what-is-the-correct-json-content-type']
});
},
BadRequestFromJoi(err) {
return this.error(
err.message,
err.error
);
},
userAlreadyExist(err) {
return this.general({
success: false,
message: 'user already registered in System',
description: 'user already registered in System'
});
},
userdoesNotExist(err) {
return this.general({
success: false,
message: err.message || 'user not registered in system',
description: 'user account does not exist in system'
});
},
commonAuthUserDataError() {
return this.error(
'Authentication error',
'token verification failed, Please try again'
);
},
tokenRequiredAuthError() {
return this.error(
'Authentication error, Token is required in Header',
'token verification failed, Please try again'
);
},
};
export default data;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/helper/twillo.ts
================================================
const twilioConfig = global['configuration'].twilio;
// import twilio from 'twilio';
const twillo = require('twilio')
const client = new twillo(twilioConfig.sid, twilioConfig.token);
let TwilioHelper = {
phone_verification(phone_number, code, callback) {
client.sendMessage({
to: phone_number,
from: twilioConfig.phone,
body: `Hello from Bal Bla e-Commerce-Hub\nYour verification code is ${code}`,
}, (err, message) => {
callback(message);
});
},
password_reset_notification(phone) {
client.sendMessage({
to: phone,
from: twilioConfig.phone,
body: `Bla Bla\nYour password has been successfully reset.`,
}, (err, message) => {
//
});
},
default_notification(phone, message) {
console.log(client);
client.sendMessage({
to: phone,
from: twilioConfig.phone,
body: `e-Commerce-Hub-TM\n${message}`,
}, (err, message) => {
//
});
}
}
export default TwilioHelper;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/lib/logger.ts
================================================
const winston = require('winston');
const moment = require('moment');
// define the custom settings for each transport (file, console)
const options = {
console: {
level: 'info',
handleExceptions: true,
json: true,
colorize: true,
timestamp() {
return moment
.utc()
.format();
},
prettyPrint: true,
humanReadableUnhandledException: true
}
};
const logger = new winston.Logger({
transports: [
// new winston.transports.File(options.file),
new winston
.transports
.Console(options.console),
],
exceptionHandlers: [
// new winston.transports.File(options.errorLog)
],
exitOnError: false, // do not exit on handled exceptions
});
// create a stream object with a 'write' function that will be used by `morgan`
logger.stream = {
write(message, encoding) {
logger.info(message);
}
};
export default logger;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/lib/mongoose.ts
================================================
/* eslint func-names:0 */
const mongoose = require('mongoose');
mongoose.promises = require('bluebird');
const { url } = global['configuration'].mongo;
const MongoConnect = function () {
const db = mongoose.connect(url, { useNewUrlParser: true }, (error) => {
if (error) {
console.log(`Mongoose default connection error: ${error}`);
} else {
console.log('mongo Connected :)');
}
});
mongoose.connection.on('connected', () => {
console.log(`Mongoose default connection open to ${url}`);
});
// If the connection throws an error
mongoose.connection.on('error', (err) => {
console.log(`Mongoose default connection error: ${err}`);
});
// When the connection is disconnected
mongoose.connection.on('disconnected', () => {
console.log('Mongoose default connection disconnected');
});
// If the Node process ends, close the Mongoose connection
process.on('SIGINT', () => {
mongoose.connection.close(() => {
console.log('Mongoose default connection disconnected through app termination');
process.exit(0);
});
});
return db;
};
export default MongoConnect;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/lib/requestValidator.ts
================================================
const Joi = require('joi');
const validation = {
loginUser : {
body : {
email: Joi.string().regex(/^[\w.]+@[\w]+?(\.[a-zA-Z]{2,3}){1,3}$/).required(),
password: Joi.string().min(8).max(50).required()
}
},
createUser: {
body: {
username: Joi.string().min(4).max(50).required(),
password: Joi.string().min(8).max(50).required(),
email: Joi.string().regex(/^[\w.]+@[\w]+?(\.[a-zA-Z]{2,3}){1,3}$/).required(),
verify_password: Joi.string().min(6).max(50).required()
},
},
resetPassword: {
body: {
email: Joi.string().regex(/^[\w.]+@[\w]+?(\.[a-zA-Z]{2,3}){1,3}$/).required(),
}
}
};
export default validation
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/middleware/authMiddleware.ts
================================================
const jwt = require("jsonwebtoken");
import responseTemplate from '../helper/responseTemplate';
import User from '../models/user';
const validation: any = {
validateToken(req, res, next) {
// validatr token here is its valid here
const token = req.headers.authorization;
if (token) {
jwt.verify(token, "secretkey", (err, data) => {
if (err) {
res.status(403).json(responseTemplate.commonAuthUserDataError());
} else {
User.findById(data.id, (error, user) => {
if(error){
res.status(403).json(responseTemplate.commonAuthUserDataError());
}
user.hasPassword = user.password ? true : false;
req.user = user;
next();
})
}
});
} else {
res.status(403).json(responseTemplate.tokenRequiredAuthError());
}
}
};
export default validation;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/middleware/requestValidator.ts
================================================
module.exports = {
validatePayload(req, res, next) {
// validatr token here is its valid here
const token = req.body;
if ((req.method === 'POST' || req.method === 'PUT') && req.body !== null) {
next();
}
res.status(403).json({ message: 'payload is required for HTTP Post & Put ' });
}
};
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/models/plugin/plugin.ts
================================================
const datePlugin = function timestamp(schema) {
// Add the two fields to the schema
schema.add({
createdAt: Date,
updatedAt: Date
})
// Create a pre-save hook
schema.pre('save', function (next) {
let now = Date.now()
this.updatedAt = now
// Set a value for createdAt only if it is null
if (!this.createdAt) {
this.createdAt = now
}
// Call the next function in the pre-save chain
next()
})
}
export default datePlugin;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/models/user.ts
================================================
const mongoose = require('mongoose');
const bcrypt = require('bcrypt-nodejs');
import helper from '../helper/bcrypt';
const { Schema } = mongoose;
import timestampPlugin from './plugin/plugin';
import Helper from '../../app/helper/bcrypt';
const userSchema = new Schema({
provider: {
type: String
},
username: {
type: String
},
password: { type: String },
email: {
index: { unique: true },
type: String
},
address: {
type: String
},
meta: mongoose.Schema.Types.Mixed,
picture : mongoose.Schema.Types.Mixed,
/*
reviews : [{
type: mongoose.Schema.ObjectId,
ref: 'Review'
}],
booking : [{
type: mongoose.Schema.ObjectId,
ref: 'Booking'
}],
vehicles: [{
type: mongoose.Schema.ObjectId,
ref: 'Vehicle'
}], */
uuid: {
type: String
},
type: {
type: String,
default: 1
},
status: {
type: String,
default: 1
},
profile_picture: mongoose.Schema.Types.Mixed,
phone: String,
email_verified: Boolean,
phone_verified: Boolean,
social: mongoose.Schema.Types.Mixed,
documents: [mongoose.Schema.Types.Mixed],
gender: Number, // 1: Male, 2: Female, 3: Unspecified
},{ toJSON: { virtuals: true } });
userSchema.set('toObject', { virtuals: true });
userSchema.set('toJSON', { virtuals: true });
userSchema.plugin(timestampPlugin)
const User = mongoose.model('User', userSchema);
export default User;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/routes/defaultRoutes.ts
================================================
import * as express from "express";
const router = express.Router();
import { Router } from "express";
export class DefaultRouter {
router: Router;
/**
* Initialize the HeroRouter
*/
constructor() {
this.router = Router();
}
/**
* @api {POST} /auth/reset-password update password sent in Mail
* @apiName resetPassword
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
public sayHello(req, res) {
res.status(200).json({ success: true, message: 'i am up and running .. ⚡️⚡️⚡️⚡️⚡️⚡️⚡️' });
};
init() {
this.router.get("/", this.sayHello);
}
}
// Create the HeroRouter, and export its configured Express.Router
const defaultRouter = new DefaultRouter();
defaultRouter.init();
export default defaultRouter.router;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/routes/provider/Facebook.ts
================================================
import * as passport from 'passport';
const FacebookStrategy = require('passport-facebook');
import userController from '../../controller/UserController';
/* eslint no-underscore-dangle: 0 */
passport.use(new FacebookStrategy(
{
clientID: global.configuration.facebook.client_id,
clientSecret: global.configuration.facebook.client_secret,
callbackURL: global.configuration.facebook.callback_url,
profileFields: ['id', 'displayName', 'photos', 'email'],
passReqToCallback: true,
},
(req, accessToken, refreshToken, profile, done) => {
const data = profile._json;
if (!data.email) {
data.email = 'ramnivas.yadav@srijan.net';
}
userController.registerSocial({
provider: 'facebook',
name: data.name,
email: data.email,
phone: '5436785432',
meta: {
provider: 'facebook',
id: profile.id,
token: accessToken,
}
}, (err, profileData) => {
if (err) {
done(err, null);
}
done(null, profileData);
});
}
));
const FacebookRoutes = {
authenticate: () => passport.authenticate('facebook', { scope: ['email', 'public_profile', 'user_location'] }),
callback: () => passport.authenticate('facebook', {
failureRedirect: '/auth/failed'
})
};
export default FacebookRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/routes/provider/Google.ts
================================================
export {}
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
import userController from '../../controller/UserController';
/* eslint no-underscore-dangle: 0 */
passport.use(new GoogleStrategy(
{
clientID: global.configuration.google.client_id,
clientSecret: global.configuration.google.client_secret,
callbackURL: `${global.configuration.url.API}/auth/callback/google`,
profileFields: ['id', 'displayName', 'photos', 'email']
},
(accessToken, refreshToken, profile, done) => {
const data = profile._json;
console.log(data);
userController.registerSocial({
provider: 'google',
username: data.displayName,
email: data.emails[0].value,
phone: '5436785432',
picture : data.image.url,
meta: {
provider: 'google',
id: data.id,
token: accessToken,
}
}, (err, profileData) => {
if (err) {
done(err, null);
}
done(null, profileData);
});
}
));
const GoogleRoutes = {
authenticate: () => passport.authenticate('google', { scope: ['profile', 'email'] }),
callback: () => passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
}
};
export default GoogleRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/routes/provider/Linkedin.ts
================================================
export {}
const passport = require('passport');
const LinkedInStrategy = require('passport-linkedin');
import userController from '../../controller/UserController';
/* eslint no-underscore-dangle: 0 */
passport.use(new LinkedInStrategy(
{
consumerKey: global.configuration.linkedin.client_id,
consumerSecret: global.configuration.linkedin.client_secret,
callbackURL: global.configuration.linkedin.callback_url,
profileFields: ['id', 'first-name', 'last-name', 'email-address', 'headline']
},
((token, tokenSecret, profile, done) => {
console.log(profile);
const data = profile._json;
userController.registerSocial({
provider: 'linkedin',
name: `${data.firstName} ${data.lastName}`,
email: data.emailAddress,
mobno: '5436785432',
meta: {
provider: 'linkedin',
id: data.id,
token,
}
}, (err, profileData) => {
if (err) {
done(err, null);
}
done(null, profileData);
});
})
));
const LinkedinRoutes = {
authenticate: () => passport.authenticate('linkedin', { scope: ['r_basicprofile', 'r_emailaddress'] }),
callback: () => passport.authenticate('linkedin', {
failureRedirect: '/auth/failed'
})
};
export default LinkedinRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/routes/provider/Locale.ts
================================================
/* eslint prefer-destructuring:0 */
const passportModule = require('passport');
const LocalStrategy = require('passport-local');
import userController from '../../controller/UserController';
const User = require('../../models/user');
const helper = require('../../helper/bcrypt');
passportModule.use(new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
session: false
},
((req, email, password, done) => {
// write code here to find user if it exists in system
User.find({ email }, (err, data) => {
if (err) {
return done(null, null);
} else if (data.length === 0) {
return done(null, null);
}
const flag = helper.comparePassword(password, data[0].password);
if (!flag) {
return done(null, null);
}
return done(null, data);
});
})
));
const localRoutes = {
authenticate() {
return passportModule.authenticate('local', { session: false });
},
authenticate_with_callback: () => passportModule.authenticate('local', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failed'
}),
};
export default localRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/routes/provider/Twitter.ts
================================================
const passport = require('passport');
const TwitterStrategy = require('passport-twitter').Strategy;
import userController from '../../controller/UserController';
passport.use(new TwitterStrategy(
{
consumerKey: global.configuration.twitter.client_id,
consumerSecret: global.configuration.twitter.client_secret,
callbackURL: 'http://127.0.0.1:3005/auth/callback/twitter'
},
(token, tokenSecret, profile, done) => {
console.log('data>>>', profile);
const data = profile;
userController.registerSocial({
provider: 'twitter',
username: data.username,
email: data.email || 'raam.yaadav@gmail.com',
mobno: '5436785432',
meta: {
provider: 'twitter',
id: data.id,
token,
}
}, (err, profileData) => {
if (err) {
done(err, null);
}
done(null, profileData);
});
}
));
const TwitterRoutes = {
authenticate: () => passport.authenticate('twitter'),
callback: () => passport.authenticate('twitter', { failureRedirect: '/auth/failed' }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
}
};
export default TwitterRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/routes/routes.ts
================================================
import * as express from "express";
import UserController from "../controller/UserController";
const jwt = require("jsonwebtoken");
// seralize user Object
const url = global['configuration'].url;
import LocaleRoute from "./provider/Locale";
import * as expressJoiValidator from "express-joi-validator";
import expressJoi from "../lib/requestValidator";
// import FacebookRoutes from "./provider/Facebook";
import GoogleRoutes from "./provider/Google";
// import LinkedinRoutes from "./provider/Linkedin";
import Template from "../helper/responseTemplate";
// import TwitterRoute from "./provider/Twitter";
import * as template from '../helper/responseTemplate';
const boom = require("express-boom");
import { Router, Request, Response, NextFunction } from "express";
import helper from '../helper/bcrypt';
import ValidAuthTokenMiddleware from '../middleware/authMiddleware';
export class AuthRouter {
router: Router;
/**
* Initialize the HeroRouter
*/
constructor() {
this.router = Router();
this.init();
}
public register(req: any, res: any) {
UserController.registerDefault(req, res, (error, user) => {
if (error) {
res.status(400).json(Template.userAlreadyExist(error.message));
} else {
res.json({
statusCode: 200,
success: true,
message: "user created successfully",
user
});
}
});
}
public login(req: any, res: any) {
UserController.validateUser(req, res, (err, token) => {
if (err) {
res.status(401).json(Template.userdoesNotExist(err));
} else {
res.status(200).json({
success: true,
message: "success",
token
});
}
});
}
public redirectSocialUser(req, res) {
jwt.sign(helper.buildUserToken(req.user), "secretkey", (tokError, token) => {
if (tokError) {
res.boom.badImplementation(tokError);
} else {
// redirect app to FE app routes with Token
console.log('redirecting Now...');
res.redirect(helper.authRedirectUrl(`?token=${token}`));
/* res.json({
statusCode: 200,
message: "success",
token
}); */
}
});
}
public validate(req: any, res: any) {
res.json({
statusCode: 200,
message: 'validated succsessfully',
success: true,
user : req.user
});
}
/**
* @api {POST} /auth/reset-password update password sent in Mail
* @apiName resetPassword
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
public resetPassword(req, res) {
UserController.resetPassword(req.body.email, (error, success) => {
console.log(error)
if (error) {
res.status(403).json({ success: false, message: error, description: 'error occoured while resetting password' });
} else {
res.json({
statusCode: 200,
message: 'success',
description: 'if this email is registered with us, you will receive a password reset email soon.',
});
}
});
};
public activateUserAccount(req, res) {
UserController.activateUserAccount(req.params.uuid, (error, success) => {
if (error) {
res.status(403).json({ success: false, message: error, description: 'error occoured while activating user' });
} else {
res.redirect(url.FE);
}
});
}
/**
* Take each handler, and attach to one of the Express.Router's
* endpoints.
*/
init() {
this.router.post("/login", expressJoiValidator(expressJoi.loginUser), this.login);
this.router.get("/validate", ValidAuthTokenMiddleware.validateToken, this.validate);
this.router.post("/register", expressJoiValidator(expressJoi.createUser), this.register);
this.router.post("/reset-password", expressJoiValidator(expressJoi.resetPassword), this.resetPassword);
this.router.get("/activate/:uuid", this.activateUserAccount);
/**
* @api {POST} /auth/login/facebook Social Login
* @apiName google
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
/*
this.router.get("/login/facebook", FacebookRoutes.authenticate());
this.router.get(
"/callback/facebook",
FacebookRoutes.callback(),
this.redirectSocialUser
);
*/
/**
* @api {POST} /auth/login/google Social Login
* @apiName google
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
this.router.get("/login/google", GoogleRoutes.authenticate());
this.router.get(
"/callback/google",
GoogleRoutes.callback(),
this.redirectSocialUser
);
/**
* @api {POST} /auth/login/twitter Social Login
* @apiName twitter
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
/*this.router.get("/login/twitter", TwitterRoute.authenticate("twitter"));
this.router.get(
"/callback/twitter",
TwitterRoute.callback(),
this.redirectSocialUser
); */
/**
* @api {POST} /auth/login/linkedin Social Login
* @apiName linkedin
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
/*
this.router.get("/login/likedin", LinkedinRoutes.authenticate());
this.router.get("/login/linkedin", LinkedinRoutes.authenticate());
this.router.get(
"/callback/linkedin",
LinkedinRoutes.callback(),
this.redirectSocialUser
); */
}
}
// Create the HeroRouter, and export its configured Express.Router
const authRoutes = new AuthRouter();
authRoutes.init();
export default authRoutes.router;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/routes/userRoutes.ts
================================================
import * as express from "express";
const router = express.Router();
const passport = require("passport");
import UserController from "../controller/UserController";
const jwt = require("jsonwebtoken");
// seralize user Object
import ResponseTemplate from '../global/templates/response';
import * as expressJoiValidator from "express-joi-validator";
import expressJoi from "../lib/requestValidator";
const boom = require("express-boom");
import { Router } from "express";
const path = require('path')
const fs = require('fs');
const { uploadpath } = global['configuration']
const multer = require('multer');
import Helper from '../helper/bcrypt';
let profileStorage = multer.diskStorage({
destination: function (req, file, cb) {
cb( null, path.join( uploadpath.uploaddir, uploadpath.profiledir ) );
},
filename: function (req, file, cb) {
let extension = Helper.getFileExtension(file.originalname);
cb( null, `${req.user.id}-${ Helper.randomString() }.${extension}` );
}
})
let upload = multer({ storage: profileStorage });
let documentStorage = multer.diskStorage({
destination: function (req, file, cb) {
cb( null, path.join( uploadpath.uploaddir, uploadpath.documentdir ) );
},
filename: function (req, file, cb) {
let extension = Helper.getFileExtension(file.originalname);
cb( null, `${req.user.id}-${ Helper.randomString() }.${extension}` );
}
})
let uploadDocuments = multer({ storage: documentStorage });
export class AuthRouter {
router: Router;
/**
* Initialize the HeroRouter
*/
constructor() {
this.router = Router();
this.init();
}
/**
* @api {POST} /auth/reset-password update password sent in Mail
* @apiName resetPassword
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
public resetPassword(req, res){
UserController.resetPassword( req.body.email, ( error, success) => {
console.log(error)
if ( error ) {
res.status(403).json({success : false, message: error, description: 'error occoured while resetting password' });
} else {
res.json({
statusCode: 200,
message: 'success',
description: 'if this email is registered with us, you will receive a password reset email soon.',
});
}
});
};
public updateUser(req, res){
UserController.updateUser(req.params.email, req.body ,( error, success) => {
if ( error ) {
res.status(403).json({success : false, message: error, description: 'error occoured while updating user' });
} else {
res.json({
statusCode: 200,
message: 'success',
description: 'user updated successfully',
});
}
});
}
public getUserByEmail(req, res){
UserController.getUserByEmail(req.params.email ,( error, user) => {
if ( error ) {
res.status(403).json({success : false, message: error, description: 'error occoured while updating user' });
} else {
res.json({
statusCode: 200,
message: 'success',
data: user
});
}
});
}
public uploadProfilepicture(req, res){
UserController.updateUser( req.user.email, { picture: req.file.filename }, ( error, user ) => {
if ( error ) {
res.json( ResponseTemplate.updateErrorOccoured(error) );
} else {
res.json( ResponseTemplate.success(
'your profile picture has been successfully uploaded',
{ picture: Helper.avatarURL(user.picture) })
);
Helper.deleteFile( 'profile', req.user.picture );
}
});
}
// upload users profile picture.
public uploadDocuments(req, res){
let documents:any = {};
req.files.map( (file) => {
documents.url = file.filename;
documents.originalname = file.originalname;
documents.timestamp = new Date();
});
UserController.updateUser( req.user.email, { document: documents }, ( error, user ) => {
if ( error ) {
res.json( ResponseTemplate.updateErrorOccoured(error) );
} else {
let userDocuments = [];
if ( user.documents ) {
user.documents.map( (doc) => {
userDocuments.push( Helper.userDocumentURL(doc.url) );
});
}
res.json( ResponseTemplate.success(
'host documents have been successfully uploaded',
{ documents: userDocuments })
);
}
});
}
/**
* Take each handler, and attach to one of the Express.Router's
* endpoints.
*/
init() {
this.router.get("/:email", this.getUserByEmail);
this.router.get("/reset-password/:email",expressJoiValidator(expressJoi.resetPassword), this.resetPassword);
this.router.put("/update/:email", this.updateUser);
this.router.post('/upload-profile-picture', upload.single('avatar'), this.uploadProfilepicture);
this.router.post('/upload-documents', uploadDocuments.array('documents'), this.uploadDocuments);
}
}
// Create the HeroRouter, and export its configured Express.Router
const authRoutes = new AuthRouter();
authRoutes.init();
export default authRoutes.router;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/routes.ts
================================================
/* eslint func-names: ["error", "never"] */
/* eslint prefer-destructuring: 0 */
import * as express from 'express';
const expressRouter= express.Router();
import authRoutes from './routes/routes';
import userRoutes from './routes/userRoutes';
import defaultRoutes from './routes/defaultRoutes';
import validAuthTokenMiddleware from './middleware/authMiddleware';
expressRouter.use('/', defaultRoutes);
expressRouter.use('/uploads/', express.static('uploads'));
expressRouter.use('/auth', authRoutes);
expressRouter.use('/user',validAuthTokenMiddleware.validateToken, userRoutes);
export default expressRouter;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/seed/seedUsers.ts
================================================
import User from '../models/user';
const mongoose = require('mongoose');
const dbName = 'blabla';
mongoose.connect(`mongodb://localhost/${dbName}`);
/* eslint quote-props:0 */
/* Aquí vamos a requerir el mongoose, en donde tengo el modelo y la base de datos que creo */
const users = [
{
'username': 'tarun',
'email': 'tarun@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun1222@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun22@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun5@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun1@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun6@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'asdfg@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tgfdsa@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},
{
'username': 'tarun1',
'email': 'tarunfgds8@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},{
'username': 'tarun1',
'email': 'asdfcv@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},{
'username': 'tarun1',
'email': 'dekoo@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},{
'username': 'tarun1',
'email': 'hellodemo@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},{
'username': 'tarun1',
'email': 'gmail@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 16.5377266,
'lng': 79.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}
];
User.collection.drop();
User.create(users, (err) => {
if (err) {
throw (err);
}
console.log(`Created ${users.length} User`);
mongoose.connection.close();
});
/* Para que se cree esta base de datos tengo que poner en terminal, en otra terminal:
node ./bin/seeds.js. De esta manera se crea la base de datos */
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/seed/seedVehicle.ts
================================================
import User from '../models/user';
const mongoose = require('mongoose');
const dbName = 'blabla';
mongoose.connect(`mongodb://localhost/${dbName}`);
/* eslint quote-props:0 */
/* Aquí vamos a requerir el mongoose, en donde tengo el modelo y la base de datos que creo */
const users = [
{
'username': 'tarun',
'email': 'tarun@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun1222@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun22@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun5@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun1@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun6@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun7@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun8@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}
];
User.collection.drop();
User.create(users, (err) => {
if (err) {
throw (err);
}
console.log(`Created ${users.length} User`);
mongoose.connection.close();
});
/* Para que se cree esta base de datos tengo que poner en terminal, en otra terminal:
node ./bin/seeds.js. De esta manera se crea la base de datos */
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/transformer/userTransformer.ts
================================================
'use strict';
import _ from 'lodash';
// import ReviewTransformer from './ReviewTransformer';
let UserTransformer = {
xx : (users) =>{
if ( Array.isArray(users) ) {
let output = [];
users.forEach(( user ) => {
output.push( UserTransformer._transformUsers(user) );
});
return output;
}
else {
return UserTransformer._transformUsers(users);
}
},
transform: (users) => {
if (Array.isArray(users)) {
let output = [];
users.forEach((user) => {
output.push(UserTransformer._transform(user));
});
return output;
}
else {
return UserTransformer._transform(users);
}
},
calculateUsers: (users: any | null) => {
if (Array.isArray(users)) {
return {
Users : users.length ? users.length : 100,
vehicles : (users['vehicle'] ) ? users['vehicle'].length : 1000,
cities :100
}
}
},
_transform: (user) => {
if (!user) { return {}; }
let user_status = (user.status === 1) ? 'active' : 'disabled';
return {
id: user._id,
username : user.username,
status: user_status,
name: user.name,
email: user.email,
password: (user.password) ? true : false,
phone: user.phone || '',
gender: user.gender || '',
birthday: user.birthday || '',
type: user.type || 1,
meta: user.meta || {},
social : user.social || [],
phone_verified: user.phone_verified ? true : false,
email_verified: user.email_verified ? true : false,
profile_picture: user.profile_picture ? null : null // will fix later
};
},
transformUsers: ( users ) => {
if ( Array.isArray(users) ) {
let output = [];
users.forEach(( user ) => {
output.push( UserTransformer._transformUsers(user) );
});
return output;
}
else {
return UserTransformer._transformUsers(users);
}
},
_transformUsers: ( user ) => {
if ( ! user ) { return {}; }
let user_status = ( user.status === '1' ) ? 'active' : 'disabled';
const obj:any = {};
return Object.assign({}, {
id: user._id,
username : user.username,
status: user_status,
name: user.name,
email_verified:user.email_verified,
phone_verified :user.phone_verified,
reviews : user.reviews,
vehciles : user.vehciles,
email: user.email,
date : user.createdAt,
type: user.type || 1,
}, obj);
}
}
export default UserTransformer;
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/types/global.d.ts
================================================
declare namespace NodeJS {
export interface Global {
configuration: any
}
}
================================================
FILE: dockerized-containers/e-Commerce-Admin/app/types/vendor.d.ts
================================================
declare namespace NodeJS {
export interface Global {
configuration: any
}
}
================================================
FILE: dockerized-containers/e-Commerce-Admin/env.sh
================================================
# this environment vairables needs to be set in .env file in applciaiton root directory
# copy this file as .env and add the appropriate values as per environment.
# node & mysql
export NODE_ENV="dev"
export PORT="3002"
export MONGOURL="mongodb://ms_commerce_mongo/blabla"
export EXPRESS_SESSION_SECRET="######################"
export F_CLIENTID="###################"
export F_CLIENTSECRET="###########################"
export F_CALLBACK="/auth/callback/facebook"
export G_CLIENTID="@@@@@@@@@@@@@-###############.apps.%%%%%%%%%%%.com"
export G_CLIENTSECRET="k##########@@@@@@@@@@@@Ub"
export G_CALLBACK="/auth/callback/google"
export L_CLIENTID="##################"
export L_CLIENTSECRET="############"
export L_CALLBACK="/auth/callback/linkedin"
export T_CLIENTID="##################"
export T_CLIENTSECRET="######################"
export T_CALLBACK="/auth/callback/twitter"
export FE_URL="localhost:3000"
export API_KEY='XX0xxxxx-xX0X0XxXXxXxXXXxX0x'
export SMTP_HOST='smtp.mandrillapp.com'
export SMTP_PORT='587'
export SMTP_USER='#############.net'
export SMTP_PASSWORD='##############'
export SID='XX0xxxxx-xX0X0XxXXxXxXXXxX0x'
export TOKEN='XX0xxxxx-xX0X0XxXXxXxXXXxX0x'
export PHONE='+9716156786'
export FE='http://localhost:3000'
export API='http://localhost:3005'
export UPLOAD_DIR='uploads'
export PROFILE_PICTURE_DIR='profile'
export DOCUMENT_UPLOAD_DIR='documents'
================================================
FILE: dockerized-containers/e-Commerce-Admin/express.ts
================================================
import router from './app/routes';
import * as boom from 'express-boom';
import * as expressSession from 'express-session';
import * as cookieParser from 'cookie-parser';
import * as passport from 'passport';
import * as helmet from 'helmet';
import * as cors from 'cors';
import * as path from 'path';
import * as express from 'express';
import * as logger from 'morgan';
import * as bodyParser from 'body-parser';
import errorHandlers from './app/helper/errorHandler';
// Creates and configures an ExpressJS web server.
class App {
// ref to Express instance
public express: express.Application;
//Run configuration methods on the Express instance.
constructor() {
this.express = express();
this.middleware();
this.routes();
}
// Configure Express middleware.
private middleware(): void {
this.express.use(passport.initialize());
// required for passport to initlize it
this.express.use(expressSession({ secret: 'bla bla' }));
this.express.use(passport.session());
// initlize session
this.express.use(logger('dev'));
this.express.disable('x-powered-by');
this.express.disable('etag');
this.express.use(helmet());
this.express.use(boom());
this.express.use(helmet.noCache({ noEtag: true })); // set Cache-Control header
this.express.use(helmet.noSniff()); // set X-Content-Type-Options header
this.express.use(helmet.frameguard()); // set X-Frame-Options header
this.express.use(helmet.xssFilter()); // set X-XSS-Protection header
// logger logs on console
this.express.use(bodyParser.urlencoded({ extended: false, limit: '5mb' })); // parse application/x-www-form-urlencoded
this.express.use(bodyParser.json()); // parse application/json
// enable CORS
this.express.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, PUT, PATCH, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, api_key, Authorization, Referer');
next();
});
// register all custom Middleware
this.express.use(cors({ optionsSuccessStatus: 200 }));
this.express.use(cookieParser()); // cookies-parser
// manage session by cookies
this.express.set('views', path.join(__dirname, 'views')); // setting views
this.express.set('view engine', 'hbs');
// server side template rendering
this.express.use(express.static(path.join(__dirname, 'public')));
this.express.use(logger('dev'));
this.express.use(bodyParser.json());
this.express.use(bodyParser.urlencoded({ extended: false }));
}
// Configure API endpoints.
private routes(): void {
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
/* This is just to get up and running, and to make sure what we've got is
* working so far. This function will change when we start to add more
* API endpoints */
this.express.use('/api/v1', router);
this.express.use(errorHandlers.internalServerError);
this.express.use(errorHandlers.PageNotFound);
}
}
export default new App().express;
================================================
FILE: dockerized-containers/e-Commerce-Admin/package.json
================================================
{
"name": "e-commerce-hub",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "cd dist && nodemon server.js",
"prestart": "tsc && cp -r uploads dist/ && cp -r app/global dist/app/",
"startdev": ". ./env.sh && cd dist && nodemon server.js",
"clean": "rm -rf dist",
"watch": "tsc",
"copy": "cp -r uploads dist/",
"test": ". ./env.sh && NODE_ENV=test && mocha ",
"debug": ". ./env.sh && NODE_ENV=test && cd dist && nodemon --inspect=0.0.0.0:9230 server.js",
"prestartdev": " npm run clean && tsc && npm run copy && npm run watch",
"watchserver" : "tsc --watch",
"dev": ". ./env.sh && ts-node server.ts",
"start-tsc": ". ./env.sh && nodemon ./dist/server.js",
"buildAndstart": ". ./env.sh && npm run build && npm run start"
},
"dependencies": {
"@types/express": "^4.11.1",
"assert": "^1.4.1",
"axios": "^0.18.0",
"bcrypt-nodejs": "0.0.3",
"bluebird": "^3.5.3",
"body-parser": "^1.18.3",
"cookie-parser": "^1.4.3",
"cors": "^2.8.5",
"dotenv": "^6.1.0",
"email-templates": "^2.7.1",
"express": "^4.16.4",
"express-boom": "^2.0.0",
"express-joi-validator": "^2.0.0",
"express-session": "^1.15.6",
"fast-csv": "^2.4.1",
"hbs": "^4.0.1",
"helmet": "^3.15.0",
"joi": "^14.1.1",
"jsonwebtoken": "^8.4.0",
"mocha": "^5.2.0",
"moment": "^2.22.2",
"mongoose": "^4.5.9",
"morgan": "^1.9.0",
"multer": "^1.2.0",
"nodemailer": "2.5.0",
"nodemon": "^1.18.6",
"passport": "0.3.2",
"passport-facebook": "2.1.1",
"passport-google-oauth": "1.0.0",
"passport-google-oauth20": "^1.0.0",
"passport-instagram": "1.0.0",
"passport-linkedin": "^1.0.0",
"passport-local": "1.0.0",
"passport-twitter": "1.0.4",
"pug": "2.0.0-beta6",
"serve-favicon": "^2.5.0",
"ts-lint": "^4.5.1",
"ts-node": "^7.0.1",
"twilio": "^2.11.1",
"typescript": "^3.1.6",
"uuid": "^3.3.2",
"winston": "^2.4.2"
},
"devDependencies": {
"@types/async": "^2.0.45",
"@types/bcrypt-nodejs": "^0.0.30",
"@types/bluebird": "^3.5.20",
"@types/body-parser": "^1.16.8",
"@types/express": "^4.11.1",
"@types/mongoose": "^4.7.34",
"@types/morgan": "^1.7.35",
"@types/node": "^9.6.39",
"@types/nodemailer": "^4.3.4",
"@types/passport": "^0.4.3",
"babel-eslint": "^8.0.1",
"eslint": "^4.19.1",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-node": "^5.2.1"
}
}
================================================
FILE: dockerized-containers/e-Commerce-Admin/public/javascripts/script.js
================================================
document.addEventListener('DOMContentLoaded', () => {
console.log('IronGenerator JS imported successfully!');
}, false);
================================================
FILE: dockerized-containers/e-Commerce-Admin/public/style.scss
================================================
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}
.h1 {
font-size: 40px;
}
================================================
FILE: dockerized-containers/e-Commerce-Admin/server.ts
================================================
import * as http from 'http';
import * as debug from 'debug';
// After you declare "app"
const env = process.env.NODE_ENV || 'dev'
console.log(` using ${process.env.NODE_ENV} to run application`);
global.configuration = require(`./app/config/environments/${env}`);
import App from './express';
const port = (process.env.PORT);
const logger = require('winston');
import mongoose from './app/lib/mongoose';
mongoose();
const server = http.createServer(App);
server.listen(process.env.PORT);
server.on('error', onError);
server.on('listening', onListening);
function onError(error: NodeJS.ErrnoException): void {
if (error.syscall !== 'listen') throw error;
let bind = (typeof port === 'string') ? 'Pipe ' + port : 'Port ' + port;
switch(error.code) {
case 'EACCES':
console.error(`${bind} requires elevated privileges`);
process.exit(1);
break;
case 'EADDRINUSE':
console.error(`${bind} is already in use`);
process.exit(1);
break;
default:
throw error;
}
}
const gracefulStopServer = function () {
// Wait 10 secs for existing connection to close and then exit.
setTimeout(() => {
logger.info('Shutting down server');
process.exit(0);
}, 1000);
};
process.on('uncaughtException', (err) => {
logger.error(err, 'Uncaught exception');
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
logger.error({
promise,
reason
}, 'unhandledRejection');
process.exit(1);
});
process.on('SIGINT', gracefulStopServer);
process.on('SIGTERM', gracefulStopServer);
function onListening(): void {
let addr = server.address();
let bind = (typeof addr === 'string') ? `pipe ${addr}` : `port ${addr.port}`;
debug(`Listening on ${bind}`);
}
================================================
FILE: dockerized-containers/e-Commerce-Admin/tsconfig.json
================================================
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"pretty": true,
"sourceMap": true,
"target": "es6",
"outDir": "./dist",
"experimentalDecorators": false,
"emitDecoratorMetadata": false,
"skipDefaultLibCheck": false,
"baseUrl": "./lib"
},
"files" : [
"./app/types/vendor.d.ts"
],
"include": [
"/**/*.ts"
],
"exclude": [
"node_modules"
]
}
================================================
FILE: dockerized-containers/e-Commerce-Admin/tslint.json
================================================
================================================
FILE: dockerized-containers/e-Commerce-Admin/uploads/documents/.gitkeep
================================================
================================================
FILE: dockerized-containers/e-Commerce-Admin/uploads/profile/.gitkeep
================================================
================================================
FILE: dockerized-containers/e-Commerce-Auth/Dockerfile
================================================
FROM node:carbon
# Create app directory
WORKDIR /usr/src/app
# Bundle app source
COPY . .
# npm install
RUN npm install
EXPOSE 3001 9201
CMD [ "npm", "run", "watchserver" ]
CMD [ "npm", "run", "startdev" ]
================================================
FILE: dockerized-containers/e-Commerce-Auth/README.md
================================================
# Application for e-commerce Hub
REST API to support application features
- Express as web framework with Typescript
- Passport js for social authentication
- Express CORS enabled
- boom for error codes & Joi for Validation
- Winston for logging and express minitor for monitoring
- Mongoose as ODM driver
- eslint validation extending airbnb styleguide
- git hooks & CI/CD in place
- Typescript based compilation tsc compiler
- TDD in progress with Mocha
- JWT based authentication
- multiple Mongoose collection with referencing
- payment gateway Integration
- Heroku deployment
- Mini e-commerce platform
# Cart Application #
"It's just simple application to provide REST APIs for mini e-commerce platform where individual can buy products and can pay the bills
```
# Application Execution
```javascript
git clone repo
npm install
npm run startdev
tsc -- watch
```
# Application configuration
```javascript
env.sh need to be added locally
export NODE_ENV="dev"
export PORT="3005"
export MONGOURL="mongodb://mongo/hello"
export EXPRESS_SESSION_SECRET="************************"
export F_CLIENTID="**************"
export F_CLIENTSECRET="**********************"
```
# Application NPM Script
```javascript
"start": "cd dist && nodemon server.js",
"prestart": "tsc && cp -r uploads dist/ && cp -r app/global dist/app/",
"clean" : "rm -rf dist",
"copy" : "cp -r uploads dist/ && cp -r app/global dist/app/"
```
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/config/email.ts
================================================
'use strict';
export default {
global: {
from: 'info@kpilibrary.com',
},
welcome: {
subject: 'Welcome to KPI Library',
},
password_reset: {
subject: 'KPI Library: Reset your password',
},
event_booked_guest: {
subject: 'KPI Library: Your Booking Has Been Confirmed',
},
event_booked_host: {
subject: 'KPI Library: Your Event Has Been Booked',
},
event_booked_guests_notification: {
subject: 'KPI Library: Your Booking Has Been Confirmed',
},
message_received: {
subject: 'KPI Library: New Message Received',
},
guest_review_email: {
subject: 'KPI Library: Event Completed',
},
alacarte_booked_guest: {
subject: 'KPI Library: Alacarte Booking Details',
},
alacarte_booked_host: {
subject: 'KPI Library: Your Alacarte Has Been Booked',
}
}
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/config/environments/dev.ts
================================================
/* eslint quote-props: 0 */
export { }
const configuration: any = {};
configuration.db = {
mysql: {
user: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
connectTimeout: 100000
},
mongo: {
host: process.env.MONGO_HOST,
port: process.env.MONGO_PORT,
uername: process.env.MONGO_USERNAME,
password: process.env.MONGO_PASSWORD,
database: process.env.MONGO_DATABASE
}
};
configuration.URL = {
frontEnd: process.env.FE_URL
}
configuration.facebook = {
client_id: process.env.F_CLIENTID,
client_secret: process.env.F_CLIENTSECRET,
callback_url: process.env.F_CALLBACK
};
configuration.google = {
client_id: process.env.G_CLIENTID,
client_secret: process.env.G_CLIENTSECRET,
callback_url: process.env.G_CALLBACK
};
configuration.linkedin = {
client_id: process.env.L_CLIENTID,
client_secret: process.env.L_CLIENTSECRET,
callback_url: process.env.L_CALLBACK
};
configuration.twitter = {
client_id: process.env.T_CLIENTID,
client_secret: process.env.T_CLIENTSECRET,
callback_url: process.env.T_CALLBACK
};
configuration.email = {
apiKey: process.env.API_KEY,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
}
}
configuration.twilio = {
sid: process.env.SID,
token: process.env.TOKEN,
phone: process.env.PHONE,
}
configuration.url = {
FE: process.env.FE,
API: process.env.API,
}
configuration.uploadpath = {
uploaddir: process.env.UPLOAD_DIR,
profiledir: process.env.PROFILE_PICTURE_DIR
}
module.exports = configuration;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/config/environments/qa.ts
================================================
/* eslint quote-props: 0 */
export { }
const configuration: any = {};
configuration.mongo = {
url: process.env.MONGODB_URI || process.env.MONGOURL,
};
configuration.URL = {
frontEnd: process.env.FE_URL
}
configuration.facebook = {
client_id: process.env.F_CLIENTID,
client_secret: process.env.F_CLIENTSECRET,
callback_url: process.env.F_CALLBACK
};
configuration.google = {
client_id: process.env.G_CLIENTID,
client_secret: process.env.G_CLIENTSECRET,
callback_url: process.env.G_CALLBACK
};
configuration.linkedin = {
client_id: process.env.L_CLIENTID,
client_secret: process.env.L_CLIENTSECRET,
callback_url: process.env.L_CALLBACK
};
configuration.twitter = {
client_id: process.env.T_CLIENTID,
client_secret: process.env.T_CLIENTSECRET,
callback_url: process.env.T_CALLBACK
};
configuration.email = {
apiKey: process.env.API_KEY,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
}
}
configuration.twilio = {
sid: process.env.SID,
token: process.env.TOKEN,
phone: process.env.PHONE,
}
configuration.url = {
FE: process.env.FE,
API: process.env.API,
}
configuration.uploadpath = {
uploaddir: process.env.UPLOAD_DIR,
profiledir: process.env.PROFILE_PICTURE_DIR
}
module.exports = configuration;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/config/environments/test.ts
================================================
/* eslint quote-props: 0 */
export { }
const configuration: any = {};
configuration.mongo = {
url: process.env.MONGODB_URI || process.env.MONGOURL,
};
configuration.URL = {
frontEnd: process.env.FE_URL
}
configuration.facebook = {
client_id: process.env.F_CLIENTID,
client_secret: process.env.F_CLIENTSECRET,
callback_url: process.env.F_CALLBACK
};
configuration.google = {
client_id: process.env.G_CLIENTID,
client_secret: process.env.G_CLIENTSECRET,
callback_url: process.env.G_CALLBACK
};
configuration.linkedin = {
client_id: process.env.L_CLIENTID,
client_secret: process.env.L_CLIENTSECRET,
callback_url: process.env.L_CALLBACK
};
configuration.twitter = {
client_id: process.env.T_CLIENTID,
client_secret: process.env.T_CLIENTSECRET,
callback_url: process.env.T_CALLBACK
};
configuration.email = {
apiKey: process.env.API_KEY,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
}
}
configuration.twilio = {
sid: process.env.SID,
token: process.env.TOKEN,
phone: process.env.PHONE,
}
configuration.url = {
FE: process.env.FE,
API: process.env.API,
}
configuration.uploadpath = {
uploaddir: process.env.UPLOAD_DIR,
profiledir: process.env.PROFILE_PICTURE_DIR
}
module.exports = configuration;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/controller/UserController.ts
================================================
const uuidv4 = require('uuid/v4');
import User from '../models/user';
declare function require(name: string);
import Helper from '../helper/bcrypt';
const jwt = require('jsonwebtoken');
import helper from '../helper/bcrypt';
import mailEvents from '../events/notification';
import logger from '../helper/logger';
import email from '../helper/email';
const saltRounds = 10;
class userController {
static getUserByEmail(email, cb) {
User.findOne({ 'email': email }, (error, user) => {
if (user) {
cb(null, user);
} else {
cb('User does not exist in system', null);
}
});
}
static validateUser(req, res, cb) {
const { body } = req;
User.find({ email: body.email })
.then((data) => {
if (data && data.length) {
const flag = helper.comparePassword(body.password, data[0].password)
if (flag) {
jwt.sign(helper.buildUserToken(data[0]), 'secretkey', (tokError, token) => {
cb(null, token);
});
} else {
cb(new Error('username password does not match'), null);
}
}
else {
cb(new Error('no user found with this account email'), null);
}
}).catch((err)=>{
console.log(err);
cb(new Error('no user found with this account email'), null);
})
}
static registerDefault(req, res, cb) {
const { body } = req;
const { location } = req;
const hash = helper.generateSaltValue(body.password);
return User.find({ email: body.email }).then((user) => {
if (user && user.length > 0) {
cb(new Error('user already regitsered with us'), null);
} else {
return User.create(this.buildUser(body, hash, location)
, (error, user) => {
if (error) {
cb(error, null);
} else {
logger.info('emitting user create event');
mailEvents.emit("welcome", user);
cb(null, user);
}
});
}
});
}
static buildUser(body, hash = null, location = null) {
const build = {
username: body.username,
phone: body.phone,
email: body.email,
email_verified: false,
phone_verified: false,
picture: body.picture ? body.picture : null,
status: 1,
gender: null,
documents: [],
type: 1,
social: body.meta,
uuid: uuidv4()
}
return hash ? Object.assign({}, build, { password: hash }) : build;
}
static registerSocial(user, callback) {
User.findOne({ email: user.email }, (error, existingUser) => {
if (existingUser) {
callback(null, (existingUser));
} else {
User.create(this.buildUser(user, null), (err, user) => {
if (err) {
callback(err, null);
} else {
callback(null, user);
mailEvents.emit("welcome", user);
}
});
}
});
}
static activateUserAccount(uuid, cb) {
User.findOne({ 'uuid': uuid }, (error, foundUser) => {
if (foundUser) {
foundUser.email_verified = true;
foundUser.save(function (err) {
if (err) {
cb('error occoured while updating record');
} else {
cb(null, 'done');
}
});
} else {
cb('User does not exist in system');
}
});
}
static resetPassword(email, callback) {
// just generate password and send new password on mail
User.findOne({ 'email': email }, (error, foundUser) => {
if (foundUser) {
let password = Math.random().toString(36).slice(2);
const hash = helper.generateSaltValue(password);
foundUser.password = hash;
foundUser.save(function (err) {
if (err) {
callback('error occoured while updating record');
} else {
mailEvents.emit("forgotPassword", foundUser, password);
callback(null, 'done');
}
});
} else {
callback('User does not exist in system with this email');
}
});
}
static changeUserRole(req, callback) {
const email = req.params.email
const body = req.body
User.findOne({ 'email': email }, (error, user) => {
if (user) {
user.type = 2;
user.save(function (err, updated_user) {
if (err) {
callback('error occoured while chaging role');
} else {
callback(null, updated_user);
}
});
}
else {
callback('user not found in system', null);
}
});
}
static updateUser(email, data, callback) {
User.findOne({ 'email': email }, (error, user) => {
if (user) {
if (data.username) { user.username = data.username; }
if (data.gender) { user.gender = data.gender; }
if (data.phone) { user.phone = data.phone; }
if (data.profile_picture) { user.profile_picture = data.profile_picture; }
if (data.password && data.password === data.confirm_password) {
const hash = helper.generateSaltValue(data.password);
user.password = hash;
}
if ( data.picture ) { user.picture = Helper.avatarURL(data.picture) }
if (data.phone_verified) {
user.phone_verified = true;
}
if (data.document) {
user.documents.push(data.document);
}
if (data.meta) {
user.meta = {
about: data.meta.about || '',
fun_fact: data.meta.fun_fact || '',
payment: data.meta.payment || '',
}
}
user.save(function (err, updated_user) {
if (err) {
callback('error occoured while updating record');
} else {
callback(null, updated_user);
}
});
} else {
callback('user not found', null);
}
});
}
}
export default userController;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/events/notification.ts
================================================
import Email from '../helper/email';
declare function require(name: string);
const events = require('events');
const winston = require('winston');
// import Twillo from '../helper/twillo';
const eventEmitter = new events.EventEmitter();
eventEmitter.on('welcome', (user) => {
winston.log('info', `sending welcome email to ${user.email}`);
// Twillo.default_notification(user.phone, 'welcome')
Email.welcome(user);
});
eventEmitter.on('forgotPassword', (user, password, uuid) => {
winston.log('info', `sending forgotPassword email to ${user.email}`);
Email.password_reset(user, password);
// Twillo.default_notification(user.phone, 'welcome')
});
export default eventEmitter;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/global/templates/emails/password-reset-email/html.pug
================================================
html(lang='en')
head
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1, shrink-to-fit=no')
title password has successfully been reset
link(href='https://fonts.googleapis.com/css?family=Rubik:300,300i,400,400i,500,500i,700,700i,900,900i', rel='stylesheet')
link(rel='shortcut icon', type='image/x-icon', href='images/favicon.ico')
link(rel='stylesheet', href='../assets/styles/style.css', type='text/css')
body(data-gr-c-s-loaded='true', style='')
.template-wrapper
table.body(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
td.container
.content
table.main
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
a.template-logo(href='../index.html')
img(src='https://kekasrijan.herokuapp.com/static/media/kpi.88a7c7c4.png', alt='')
p.lead
| Hello #{user.email},
br
| Your password has successfully been reset
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td.mt30.mb30(align='center')
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
p.user-text
span Your new password is #[pre #{password}]
br
a.btn-primary(href= login_url) Login
p Thank you
p.mb0
| If you have any problems, please contact me at
a.click-link(href='#') admin@gmail.com
table.help-section
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
h2.text-center.mb0 Need more help?
a.support-link(href='#') We're here,ready to here
table
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
p
| You received this email beacuse you just signed up for new account. If it look weird
a.default-link(href='#') view it in your browser
.footer
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td.content-block
p.text-center
| © 2018 KPI App, Goa India
br
| If these emails get annoying, please feel to
a(href='#') unsubscribe
td
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/global/templates/emails/password-reset-email/style.css
================================================
@charset "UTF-8";
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
.container {
display: block;
Margin: 0 auto !important;
max-width: 580px;
padding: 10px;
width: 580px;
position: relative;
bottom: 140px;
}
img {
border: none;
-ms-interpolation-mode: bicubic;
max-width: 100%;
}
body {
background-color: #f6f6f6;
font-family: 'Rubik', sans-serif;
font-size: 15px;
line-height: 28px;
-webkit-font-smoothing: antialiased;
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
}
table td {
font-family: sans-serif;
font-size: 14px;
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
.body {
background-color: #f6f6f6;
width: 100%;
}
.lead {
font-size: 18px;
}
.mt30 {
margin-top: 30px;
display: block;
}
.mb30 {
margin-bottom: 30px;
display: block;
}
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
.container {
display: block;
Margin: 0 auto !important;
/* makes it centered */
max-width: 580px;
padding: 10px;
width: 580px;
position: relative;
bottom: 140px;
}
/* This should also be a block element, so that it will fill 100% of the .container */
.content {
box-sizing: border-box;
display: block;
Margin: 0 auto;
max-width: 580px;
padding: 10px;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.template-wrapper {
background-color: #03A9F4;
width: 100%;
height: 250px;
position: relative;
}
.click-link {
color: #03A9F4;
display: inline-block;
margin-bottom: 20px;
}
.help-section {
background-color: #ffdcdc;
border-radius: 3px;
width: 100%;
text-align: center;
}
.mb0 {
margin-bottom: 0px;
}
.support-link {
color: #03A9F4;
display: inline-block;
font-size: 19px;
margin-bottom: 0px;
}
.template-logo {
display: block;
margin-bottom: 40px;
margin: auto;
}
.user-text {
font-size: 18px;
font-weight: 500;
}
.user-text span {
font-weight: 600;
}
.text-secondary {
color: #218ef4 !important
}
.main {
background: #ffffff;
border-radius: 3px;
width: 100%;
margin-bottom: 20px;
}
.wrapper {
box-sizing: border-box;
padding: 40px 25px;
}
.content-block {
padding-bottom: 10px;
padding-top: 10px;
line-height: 2;
}
.footer {
clear: both;
text-align: center;
width: 100%;
}
.footer td, .footer p, .footer span, .footer a {
color: #999999;
font-size: 12px;
text-align: center;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1, h2, h3, h4 {
color: #000000;
font-family: sans-serif;
font-weight: 400;
line-height: 1.4;
margin: 0;
Margin-bottom: 30px;
}
h1 {
font-size: 35px;
font-weight: 300;
text-align: center;
text-transform: capitalize;
}
p, ul, ol {
font-family: sans-serif;
font-size: 15px;
font-weight: normal;
margin: 0;
margin-bottom: 15px;
}
p li, ul li, ol li {
list-style-position: inside;
margin-left: 5px;
}
a {
color: #3498db;
text-decoration: underline;
}
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
width: 100%;
}
.btn>tbody>tr>td {
padding-bottom: 15px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 5px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 1px #3498db;
border-radius: 5px;
box-sizing: border-box;
color: #3498db;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 12px 25px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background-color: #3498db;
}
.btn-primary a {
background-color: #03A9F4;
border-color: #03A9F4;
color: #ffffff;
}
.default-link {
color: #03A9F4;
}
.default-link:hover {
color: #03A9F4;
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
hr {
border: 0;
border-bottom: 1px solid #f6f6f6;
Margin: 20px 0;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class=body] p, table[class=body] ul, table[class=body] ol, table[class=body] td, table[class=body] span, table[class=body] a {
font-size: 16px !important;
}
table[class=body] .wrapper, table[class=body] .article {
padding: 10px !important;
}
table[class=body] .content {
padding: 0 !important;
}
table[class=body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=body] .btn table {
width: 100% !important;
}
table[class=body] .btn a {
width: 100% !important;
}
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
.btn-primary table td:hover {
background-color: #34495e !important;
}
.btn-primary a:hover {
background-color: #03A9F4 !important;
border-color: #03A9F4 !important;
}
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #03A9F4;
border: solid #03A9F4;
border-width: 6px 18px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 28px;*/
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
border-radius: 4px;
text-transform: capitalize;
}
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/global/templates/emails/welcome-email/html.pug
================================================
html(lang='en')
head
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1, shrink-to-fit=no')
title Account Activation email || KPI Library
link(href='https://fonts.googleapis.com/css?family=Rubik:300,300i,400,400i,500,500i,700,700i,900,900i', rel='stylesheet')
link(rel='shortcut icon', type='image/x-icon', href='images/favicon.ico')
link(rel='stylesheet', href='../assets/styles/style.css', type='text/css')
body(data-gr-c-s-loaded='true', style='')
.template-wrapper
table.body(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
td.container
.content
table.main
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
a.template-logo(href='../index.html')
img(src='https://kekasrijan.herokuapp.com/static/media/kpi.88a7c7c4.png', alt='')
p.lead
| Hello KPI Library,
br
| Thanks for Signup on KPI App
br
| We have sent User Account Activation Link below
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td.mt30.mb30(align='center')
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
p.user-text
| Hi,
span #{user.email},
br
br
a.btn-primary(href= activate_url) Activate your Account
p Thank you
p.mb0
| If you have any problems, please contact me at
a.click-link(href='#') admin@gmail.com
table.help-section
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
h2.text-center.mb0 Need more help?
a.support-link(href='#') We're here,ready to here
table
tbody
tr
td.wrapper
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td
p
| You received this email beacuse you just signed up for new account. If it look weird
a.default-link(href='#') view it in your browser
.footer
table(border='0', cellpadding='0', cellspacing='0')
tbody
tr
td.content-block
p.text-center
| © 2018 KPI App, Goa India
br
| If these emails get annoying, please feel to
a(href='#') unsubscribe
td
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/global/templates/emails/welcome-email/style.css
================================================
@charset "UTF-8";
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
.container {
display: block;
Margin: 0 auto !important;
max-width: 580px;
padding: 10px;
width: 580px;
position: relative;
bottom: 140px;
}
img {
border: none;
-ms-interpolation-mode: bicubic;
max-width: 100%;
}
body {
background-color: #f6f6f6;
font-family: 'Rubik', sans-serif;
font-size: 15px;
line-height: 28px;
-webkit-font-smoothing: antialiased;
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
}
table td {
font-family: sans-serif;
font-size: 14px;
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
.body {
background-color: #f6f6f6;
width: 100%;
}
.lead {
font-size: 18px;
}
.mt30 {
margin-top: 30px;
display: block;
}
.mb30 {
margin-bottom: 30px;
display: block;
}
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
.container {
display: block;
Margin: 0 auto !important;
/* makes it centered */
max-width: 580px;
padding: 10px;
width: 580px;
position: relative;
bottom: 140px;
}
/* This should also be a block element, so that it will fill 100% of the .container */
.content {
box-sizing: border-box;
display: block;
Margin: 0 auto;
max-width: 580px;
padding: 10px;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.template-wrapper {
background-color: #03A9F4;
width: 100%;
height: 250px;
position: relative;
}
.click-link {
color: #03A9F4;
display: inline-block;
margin-bottom: 20px;
}
.help-section {
background-color: #ffdcdc;
border-radius: 3px;
width: 100%;
text-align: center;
}
.mb0 {
margin-bottom: 0px;
}
.support-link {
color: #03A9F4;
display: inline-block;
font-size: 19px;
margin-bottom: 0px;
}
.template-logo {
display: block;
margin-bottom: 40px;
margin: auto;
}
.user-text {
font-size: 18px;
font-weight: 500;
}
.user-text span {
font-weight: 600;
}
.text-secondary {
color: #218ef4 !important
}
.main {
background: #ffffff;
border-radius: 3px;
width: 100%;
margin-bottom: 20px;
}
.wrapper {
box-sizing: border-box;
padding: 40px 25px;
}
.content-block {
padding-bottom: 10px;
padding-top: 10px;
line-height: 2;
}
.footer {
clear: both;
text-align: center;
width: 100%;
}
.footer td, .footer p, .footer span, .footer a {
color: #999999;
font-size: 12px;
text-align: center;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1, h2, h3, h4 {
color: #000000;
font-family: sans-serif;
font-weight: 400;
line-height: 1.4;
margin: 0;
Margin-bottom: 30px;
}
h1 {
font-size: 35px;
font-weight: 300;
text-align: center;
text-transform: capitalize;
}
p, ul, ol {
font-family: sans-serif;
font-size: 15px;
font-weight: normal;
margin: 0;
margin-bottom: 15px;
}
p li, ul li, ol li {
list-style-position: inside;
margin-left: 5px;
}
a {
color: #3498db;
text-decoration: underline;
}
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
width: 100%;
}
.btn>tbody>tr>td {
padding-bottom: 15px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 5px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 1px #3498db;
border-radius: 5px;
box-sizing: border-box;
color: #3498db;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 12px 25px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background-color: #3498db;
}
.btn-primary a {
background-color: #3498db;
border-color: #3498db;
color: #ffffff;
}
.default-link {
color: #3498db;
}
.default-link:hover {
color: #3498db;
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
hr {
border: 0;
border-bottom: 1px solid #f6f6f6;
Margin: 20px 0;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class=body] p, table[class=body] ul, table[class=body] ol, table[class=body] td, table[class=body] span, table[class=body] a {
font-size: 16px !important;
}
table[class=body] .wrapper, table[class=body] .article {
padding: 10px !important;
}
table[class=body] .content {
padding: 0 !important;
}
table[class=body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=body] .btn table {
width: 100% !important;
}
table[class=body] .btn a {
width: 100% !important;
}
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
.btn-primary table td:hover {
background-color: #34495e !important;
}
.btn-primary a:hover {
background-color: #03A9F4 !important;
border-color: #03A9F4 !important;
}
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #03A9F4;
border: solid #03A9F4;
border-width: 6px 18px;
line-height: 2em;
/* 2em * 14px = 28px, use px to get airier line-height also in Thunderbird, and Yahoo!, Outlook.com, AOL webmail clients */
/*line-height: 28px;*/
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
border-radius: 4px;
text-transform: capitalize;
}
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/global/templates/response/index.ts
================================================
class ResponseTemplate {
static general(data) {
return data;
}
static error(code, message, description) {
return {
statusCode: code || 400,
message: message || 'some error occoured',
description: description || 'error occoured on server, please try again after some time.'
};
}
static authError() {
return this.error(
403,
'authentication error',
'no authentication token provided, please login first and provide the authentication token.'
);
}
static invalidAuthError() {
return this.error(
403,
'authentication error',
'invalid Token provided, please login first and provide the authentication token.'
);
}
static emptyContent() {
return this.general({
statusCode: 402,
message: 'empty content found',
description: 'you must provide valid data and it must not be empty.',
helpful_links: ['http://stackoverflow.com/questions/18419428/what-is-the-minimum-valid-json']
});
}
static invalidContentType() {
return this.general({
statusCode: 400,
message: 'invalid content type',
description: 'you must specify content type and it must be application/json',
helpful_links: ['http://stackoverflow.com/questions/477816/what-is-the-correct-json-content-type']
});
}
static routeNotFound() {
return this.error(
405,
'resource not found',
'the resource your tried to access doesn\'t exist or you dont have permissions to access it.'
);
}
static userNotFound() {
return this.error(
400,
'user not found',
"the user you're looking for doesn't exist or you dont have permissions to access it."
);
}
static updateErrorOccoured(error) {
return this.error(
301,
'error occoured',
error || 'error occoured while updating your data.'
);
}
static success(description, data=null) {
return {
statusCode: 200,
message: 'success',
description: description || 'data successfully saved.',
...data
}
}
}
export default ResponseTemplate;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/helper/bcrypt.ts
================================================
const bcrypt = require('bcrypt-nodejs');
const jwt = require('jsonwebtoken');
const {url} = global['configuration']
const {uploadpath} = global['configuration']
const path = require('path');
const fs = require('fs');
const helper = {
generateSaltValue(password) {
const salt = bcrypt.genSaltSync(); // enter number of rounds, default: 10
const hash = bcrypt.hashSync(password, salt);
return hash;
},
comparePassword(userPassword, password ) {
if (!userPassword.length || !( password && password.length > 0) ) {
return false;
}
return bcrypt.compareSync(userPassword, password);
},
authRedirectUrl( path ) {
return `${url.FE}/#/auth/validate-token/${path}`;
},
buildUserToken(data) {
return {
email: data.email,
id:data._id,
username: data.username ? data.username : data.email,
hasPassword: data.password ? true : false,
type : data.type || 1,
picture : data.picture
}
},
resource( path ) {
return `${url.API}${path}`;
},
getFileExtension( file ) {
let extensions = file.split('.');
if ( extensions.length === 1 ) {
return 'jpg';
} else {
return extensions.pop();
}
},
avatarURL( filename ) {
if ( filename.includes('://') ) {
return filename;
}
return this.resource(`/${uploadpath.uploaddir}/${uploadpath.profiledir}/${filename}`);
},
userDocumentURL( filename ) {
if ( filename.includes('://') ) {
return filename;
}
return this.resource(`/${uploadpath.uploaddir}/${uploadpath.documentdir}/${filename}`);
},
randomString() {
return Math.random().toString(36).substring(2, 7);
},
deleteFile( type, filename ) {
let location;
if ( type === 'profile' ) { location = path.join( uploadpath.uploaddir, uploadpath.profiledir ) }
else { location = uploadpath.uploaddir; }
if (filename) {
fs.unlink( path.join( location, filename ), () => {
// in case we need to perform additional operations.
});
}
},
getPaymentMethodName( method ) {
if ( method == 1 ) { return 'PayPal'; }
else if ( method == 2 ) { return 'PayPal'; }
else if ( method == 3 ) { return 'Instamojo'; }
else { return 'Not Specified'; }
},
getCurrency(currency) {
let allCurrency = {
1: 'USD',
2: 'INR',
};
if( allCurrency[currency] ) {
return allCurrency[currency];
} else {
return allCurrency[1];
}
},
verificationCode() {
let code = Math.floor((Math.random()*999999)+111111);
return code;
}
};
export default helper;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/helper/email.ts
================================================
const path = require('path');
declare function require(name:string);
const nodemailer = require('nodemailer');
const url = global['configuration'].url;
const mailConfig = global['configuration'].email;
import emailConfig from '../config/email';
import { EmailTemplate } from 'email-templates';
// const Twillo = require('./twillo');
const transport = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
// type: 'OAuth2',
user: mailConfig.auth.user,
pass: mailConfig.auth.pass
},
});
const Email = {
welcome(user) {
if (user.email) {
let templateDir = path.join('app/global/templates', 'emails', 'welcome-email');
let welcomeEmail = new EmailTemplate(templateDir);
welcomeEmail.render({ user: user, activate_url: `${url.API}/auth/activate/${user.uuid}` }, (err, result) => {
transport.sendMail(
{
from: emailConfig.global.from,
to: user.email,
subject: emailConfig.welcome.subject,
html: result.html,
}, (err, info) => {
// some error occoured...
console.log(err);
}
);
});
}
},
password_reset(user, password) {
if (user.email) {
let templateDir = path.join('app/global/templates', 'emails', 'password-reset-email');
let passwordResetEmail = new EmailTemplate(templateDir);
passwordResetEmail.render({ user: user, login_url: `${url.FE}/#/auth/login`, password: password }, (err, result) => {
transport.sendMail(
{
from: emailConfig.global.from,
to: user.email,
subject: emailConfig.password_reset.subject,
html: result.html,
}, (err, info) => {
// some error occoured...
}
);
});
}
if (user.phone_verified) {
// Twillo.password_reset_notification(user.phone);
}
},
};
export default Email;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/helper/errorHandler.ts
================================================
import * as winston from 'winston';
import ResponseTemplate from './responseTemplate';
/* eslint class-methods-use-this:0 */
const env = process.env.NODE_ENV;
const onDevEnv = env === 'dev' || env === 'test' || env === 'local';
class errorHandler {
public internalServerError(err, req, res, next) {
winston.log('info',err);
if (err.isBoom) {
// Error From joi express validator
const error = {
message: err.output.payload.error,
error: err.output.payload.message
};
res.status(400).json(ResponseTemplate.BadRequestFromJoi(error));
} else { // internalServerError
res.status(500).json({
success: false,
message: err.message,
error: (onDevEnv) ? err.stack : {}
});
}
}
public PageNotFound(req, res, err) {
res.status(404).json({ message: 'api not found' });
}
}
export default new errorHandler();
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/helper/logger.ts
================================================
const winston = require('winston');
// define the custom settings for each transport (file, console)
const options = {
console: {
level: 'info',
handleExceptions: true,
json: true,
colorize: true,
prettyPrint: true,
humanReadableUnhandledException: true
}
};
const logger = new winston.Logger({
transports: [
// new winston.transports.File(options.file),
new winston
.transports
.Console(options.console),
],
exceptionHandlers: [
// new winston.transports.File(options.errorLog)
],
exitOnError: false, // do not exit on handled exceptions
});
// create a stream object with a 'write' function that will be used by `morgan`
logger.stream = {
write(message, encoding) {
logger.info(message);
}
};
export default logger;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/helper/responseTemplate.ts
================================================
/* istanbul ignore file */
const data: any = {
general(data) {
return data;
},
successMessage(message) {
return {
success: true,
message
};
},
success(data, message) {
return {
success: true,
message,
data
};
},
error(message, err, code= null) {
return {
success: false,
message: message || 'some error occurred',
error: err || 'error occurred on server, please try again after some time.'
};
},
emptyContent() {
return this.general({
message: 'empty content found',
description: 'you must provide valid data and it must not be empty.',
helpful_links: ['http://stackoverflow.com/questions/18419428/what-is-the-minimum-valid-json']
});
},
invalidContentType() {
return this.general({
message: 'invalid content type',
description: 'you must specify content type and it must be application/json',
helpful_links: ['http://stackoverflow.com/questions/477816/what-is-the-correct-json-content-type']
});
},
BadRequestFromJoi(err) {
return this.error(
err.message,
err.error
);
},
userAlreadyExist(err) {
return this.general({
success: false,
message: 'user already registered in System',
description: 'user already registered in System'
});
},
userdoesNotExist(err) {
return this.general({
success: false,
message: err.message || 'user not registered in system',
description: 'user account does not exist in system'
});
},
commonAuthUserDataError() {
return this.error(
'Authentication error',
'token verification failed, Please try again'
);
},
tokenRequiredAuthError() {
return this.error(
'Authentication error, Token is required in Header',
'token verification failed, Please try again'
);
},
};
export default data;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/helper/twillo.ts
================================================
const twilioConfig = global['configuration'].twilio;
// import twilio from 'twilio';
const twillo = require('twilio')
const client = new twillo(twilioConfig.sid, twilioConfig.token);
let TwilioHelper = {
phone_verification(phone_number, code, callback) {
client.sendMessage({
to: phone_number,
from: twilioConfig.phone,
body: `Hello from Bal Bla e-Commerce-Hub\nYour verification code is ${code}`,
}, (err, message) => {
callback(message);
});
},
password_reset_notification(phone) {
client.sendMessage({
to: phone,
from: twilioConfig.phone,
body: `Bla Bla\nYour password has been successfully reset.`,
}, (err, message) => {
//
});
},
default_notification(phone, message) {
console.log(client);
client.sendMessage({
to: phone,
from: twilioConfig.phone,
body: `e-Commerce-Hub-TM\n${message}`,
}, (err, message) => {
//
});
}
}
export default TwilioHelper;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/lib/logger.ts
================================================
const winston = require('winston');
const moment = require('moment');
// define the custom settings for each transport (file, console)
const options = {
console: {
level: 'info',
handleExceptions: true,
json: true,
colorize: true,
timestamp() {
return moment
.utc()
.format();
},
prettyPrint: true,
humanReadableUnhandledException: true
}
};
const logger = new winston.Logger({
transports: [
// new winston.transports.File(options.file),
new winston
.transports
.Console(options.console),
],
exceptionHandlers: [
// new winston.transports.File(options.errorLog)
],
exitOnError: false, // do not exit on handled exceptions
});
// create a stream object with a 'write' function that will be used by `morgan`
logger.stream = {
write(message, encoding) {
logger.info(message);
}
};
export default logger;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/lib/mongoose.ts
================================================
/* eslint no-undef: 0 */
/* eslint import/no-dynamic-require: 0 */
// Bring Mongoose into the app
const env = process.env.NODE_ENV || 'dev';
const global1 = require(`../config/environments/${env}`);
const mongoConfig = global1['db'].mongo;
const mongoose = require('mongoose');
// Build the connection string
let dbURI = `mongodb://${mongoConfig.host}:${mongoConfig.port}/${mongoConfig.database}`;
//if(env === 'test' || env === 'dev'){
// dbURI += '?authSource=admin'
//}
const authOptions = {
auth: {
user: mongoConfig.uername,
password: mongoConfig.password
}
};
const connect = () => {
// Create the database connection
mongoose.connect(dbURI, (err) => {
if (err) {
console.log(err.message);
} else {
console.log('Mongoose Connected! to Database');
}
});
// CONNECTION EVENTS
// When successfully connected
mongoose.connection.on('connected', () => {
console.log(`Mongoose default connection open to ${dbURI}`);
});
// If the connection throws an error
mongoose.connection.on('error', (err) => {
console.log(`Mongoose default connection error: ${err}`);
});
// When the connection is disconnected
mongoose.connection.on('disconnected', () => {
console.log('Mongoose default connection disconnected');
});
// If the Node process ends, close the Mongoose connection
process.on('SIGINT', () => {
mongoose.connection.close(() => {
console.log('Mongoose default connection disconnected through app termination');
process.exit(0);
});
});
}
export default connect;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/lib/requestValidator.ts
================================================
const Joi = require('joi');
const validation = {
loginUser : {
body : {
email: Joi.string().regex(/^[\w.]+@[\w]+?(\.[a-zA-Z]{2,3}){1,3}$/).required(),
password: Joi.string().min(8).max(50).required()
}
},
createUser: {
body: {
username: Joi.string().min(4).max(50).required(),
password: Joi.string().min(8).max(50).required(),
email: Joi.string().regex(/^[\w.]+@[\w]+?(\.[a-zA-Z]{2,3}){1,3}$/).required(),
verify_password: Joi.string().min(6).max(50).required()
},
},
resetPassword: {
body: {
email: Joi.string().regex(/^[\w.]+@[\w]+?(\.[a-zA-Z]{2,3}){1,3}$/).required(),
}
}
};
export default validation
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/middleware/authMiddleware.ts
================================================
const jwt = require("jsonwebtoken");
import responseTemplate from '../helper/responseTemplate';
import User from '../models/user';
const validation: any = {
validateToken(req, res, next) {
// validatr token here is its valid here
const token = req.headers.authorization;
if (token) {
jwt.verify(token, "secretkey", (err, data) => {
if (err) {
res.status(403).json(responseTemplate.commonAuthUserDataError());
} else {
User.findById(data.id, (error, user) => {
if(error){
res.status(403).json(responseTemplate.commonAuthUserDataError());
}
user.hasPassword = user.password ? true : false;
req.user = user;
next();
})
}
});
} else {
res.status(403).json(responseTemplate.tokenRequiredAuthError());
}
}
};
export default validation;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/middleware/requestValidator.ts
================================================
module.exports = {
validatePayload(req, res, next) {
// validatr token here is its valid here
const token = req.body;
if ((req.method === 'POST' || req.method === 'PUT') && req.body !== null) {
next();
}
res.status(403).json({ message: 'payload is required for HTTP Post & Put ' });
}
};
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/models/plugin/plugin.ts
================================================
const datePlugin = function timestamp(schema) {
// Add the two fields to the schema
schema.add({
createdAt: Date,
updatedAt: Date
})
// Create a pre-save hook
schema.pre('save', function (next) {
let now = Date.now()
this.updatedAt = now
// Set a value for createdAt only if it is null
if (!this.createdAt) {
this.createdAt = now
}
// Call the next function in the pre-save chain
next()
})
}
export default datePlugin;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/models/user.ts
================================================
const mongoose = require('mongoose');
const bcrypt = require('bcrypt-nodejs');
import helper from '../helper/bcrypt';
const { Schema } = mongoose;
import timestampPlugin from './plugin/plugin';
import Helper from '../../app/helper/bcrypt';
const userSchema = new Schema({
provider: {
type: String
},
username: {
type: String
},
password: { type: String },
email: {
index: { unique: true },
type: String
},
address: {
type: String
},
meta: mongoose.Schema.Types.Mixed,
picture : mongoose.Schema.Types.Mixed,
/*
reviews : [{
type: mongoose.Schema.ObjectId,
ref: 'Review'
}],
booking : [{
type: mongoose.Schema.ObjectId,
ref: 'Booking'
}],
vehicles: [{
type: mongoose.Schema.ObjectId,
ref: 'Vehicle'
}], */
uuid: {
type: String
},
type: {
type: String,
default: 1
},
status: {
type: String,
default: 1
},
profile_picture: mongoose.Schema.Types.Mixed,
phone: String,
email_verified: Boolean,
phone_verified: Boolean,
social: mongoose.Schema.Types.Mixed,
documents: [mongoose.Schema.Types.Mixed],
gender: Number, // 1: Male, 2: Female, 3: Unspecified
},{ toJSON: { virtuals: true } });
userSchema.set('toObject', { virtuals: true });
userSchema.set('toJSON', { virtuals: true });
userSchema.plugin(timestampPlugin)
const User = mongoose.model('User', userSchema);
export default User;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/routes/defaultRoutes.ts
================================================
import * as express from "express";
const router = express.Router();
import { Router } from "express";
export class DefaultRouter {
router: Router;
/**
* Initialize the HeroRouter
*/
constructor() {
this.router = Router();
}
/**
* @api {POST} /auth/reset-password update password sent in Mail
* @apiName resetPassword
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
public sayHello(req, res) {
res.status(200).json({ success: true, message: 'i am up and running node + mongo .. ⚡️⚡️⚡️⚡️⚡️⚡️⚡️' });
};
init() {
this.router.get("/", this.sayHello);
}
}
// Create the HeroRouter, and export its configured Express.Router
const defaultRouter = new DefaultRouter();
defaultRouter.init();
export default defaultRouter.router;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/routes/provider/Facebook.ts
================================================
import * as passport from 'passport';
const FacebookStrategy = require('passport-facebook');
import userController from '../../controller/UserController';
/* eslint no-underscore-dangle: 0 */
passport.use(new FacebookStrategy(
{
clientID: global.configuration.facebook.client_id,
clientSecret: global.configuration.facebook.client_secret,
callbackURL: global.configuration.facebook.callback_url,
profileFields: ['id', 'displayName', 'photos', 'email'],
passReqToCallback: true,
},
(req, accessToken, refreshToken, profile, done) => {
const data = profile._json;
if (!data.email) {
data.email = 'ramnivas.yadav@srijan.net';
}
userController.registerSocial({
provider: 'facebook',
name: data.name,
email: data.email,
phone: '5436785432',
meta: {
provider: 'facebook',
id: profile.id,
token: accessToken,
}
}, (err, profileData) => {
if (err) {
done(err, null);
}
done(null, profileData);
});
}
));
const FacebookRoutes = {
authenticate: () => passport.authenticate('facebook', { scope: ['email', 'public_profile', 'user_location'] }),
callback: () => passport.authenticate('facebook', {
failureRedirect: '/auth/failed'
})
};
export default FacebookRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/routes/provider/Google.ts
================================================
export {}
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
import userController from '../../controller/UserController';
/* eslint no-underscore-dangle: 0 */
passport.use(new GoogleStrategy(
{
clientID: global.configuration.google.client_id,
clientSecret: global.configuration.google.client_secret,
callbackURL: `${global.configuration.url.API}/auth/callback/google`,
profileFields: ['id', 'displayName', 'photos', 'email']
},
(accessToken, refreshToken, profile, done) => {
const data = profile._json;
console.log(data);
userController.registerSocial({
provider: 'google',
username: data.displayName,
email: data.emails[0].value,
phone: '5436785432',
picture : data.image.url,
meta: {
provider: 'google',
id: data.id,
token: accessToken,
}
}, (err, profileData) => {
if (err) {
done(err, null);
}
done(null, profileData);
});
}
));
const GoogleRoutes = {
authenticate: () => passport.authenticate('google', { scope: ['profile', 'email'] }),
callback: () => passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
}
};
export default GoogleRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/routes/provider/Linkedin.ts
================================================
export {}
const passport = require('passport');
const LinkedInStrategy = require('passport-linkedin');
import userController from '../../controller/UserController';
/* eslint no-underscore-dangle: 0 */
passport.use(new LinkedInStrategy(
{
consumerKey: global.configuration.linkedin.client_id,
consumerSecret: global.configuration.linkedin.client_secret,
callbackURL: global.configuration.linkedin.callback_url,
profileFields: ['id', 'first-name', 'last-name', 'email-address', 'headline']
},
((token, tokenSecret, profile, done) => {
console.log(profile);
const data = profile._json;
userController.registerSocial({
provider: 'linkedin',
name: `${data.firstName} ${data.lastName}`,
email: data.emailAddress,
mobno: '5436785432',
meta: {
provider: 'linkedin',
id: data.id,
token,
}
}, (err, profileData) => {
if (err) {
done(err, null);
}
done(null, profileData);
});
})
));
const LinkedinRoutes = {
authenticate: () => passport.authenticate('linkedin', { scope: ['r_basicprofile', 'r_emailaddress'] }),
callback: () => passport.authenticate('linkedin', {
failureRedirect: '/auth/failed'
})
};
export default LinkedinRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/routes/provider/Locale.ts
================================================
/* eslint prefer-destructuring:0 */
const passportModule = require('passport');
const LocalStrategy = require('passport-local');
import userController from '../../controller/UserController';
const User = require('../../models/user');
const helper = require('../../helper/bcrypt');
passportModule.use(new LocalStrategy(
{
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true,
session: false
},
((req, email, password, done) => {
// write code here to find user if it exists in system
User.find({ email }, (err, data) => {
if (err) {
return done(null, null);
} else if (data.length === 0) {
return done(null, null);
}
const flag = helper.comparePassword(password, data[0].password);
if (!flag) {
return done(null, null);
}
return done(null, data);
});
})
));
const localRoutes = {
authenticate() {
return passportModule.authenticate('local', { session: false });
},
authenticate_with_callback: () => passportModule.authenticate('local', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failed'
}),
};
export default localRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/routes/provider/Twitter.ts
================================================
const passport = require('passport');
const TwitterStrategy = require('passport-twitter').Strategy;
import userController from '../../controller/UserController';
passport.use(new TwitterStrategy(
{
consumerKey: global.configuration.twitter.client_id,
consumerSecret: global.configuration.twitter.client_secret,
callbackURL: 'http://127.0.0.1:3005/auth/callback/twitter'
},
(token, tokenSecret, profile, done) => {
console.log('data>>>', profile);
const data = profile;
userController.registerSocial({
provider: 'twitter',
username: data.username,
email: data.email || 'raam.yaadav@gmail.com',
mobno: '5436785432',
meta: {
provider: 'twitter',
id: data.id,
token,
}
}, (err, profileData) => {
if (err) {
done(err, null);
}
done(null, profileData);
});
}
));
const TwitterRoutes = {
authenticate: () => passport.authenticate('twitter'),
callback: () => passport.authenticate('twitter', { failureRedirect: '/auth/failed' }),
function(req, res) {
// Successful authentication, redirect home.
res.redirect('/');
}
};
export default TwitterRoutes;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/routes/routes.ts
================================================
import * as express from "express";
import UserController from "../controller/UserController";
const jwt = require("jsonwebtoken");
// seralize user Object
const url = global['configuration'].url;
import LocaleRoute from "./provider/Locale";
import * as expressJoiValidator from "express-joi-validator";
import expressJoi from "../lib/requestValidator";
// import FacebookRoutes from "./provider/Facebook";
import GoogleRoutes from "./provider/Google";
// import LinkedinRoutes from "./provider/Linkedin";
import Template from "../helper/responseTemplate";
// import TwitterRoute from "./provider/Twitter";
import * as template from '../helper/responseTemplate';
const boom = require("express-boom");
import { Router, Request, Response, NextFunction } from "express";
import helper from '../helper/bcrypt';
import ValidAuthTokenMiddleware from '../middleware/authMiddleware';
export class AuthRouter {
router: Router;
/**
* Initialize the HeroRouter
*/
constructor() {
this.router = Router();
this.init();
}
public register(req: any, res: any) {
UserController.registerDefault(req, res, (error, user) => {
if (error) {
res.status(400).json(Template.userAlreadyExist(error.message));
} else {
res.json({
statusCode: 200,
success: true,
message: "user created successfully",
user
});
}
});
}
public login(req: any, res: any) {
UserController.validateUser(req, res, (err, token) => {
if (err) {
res.status(401).json(Template.userdoesNotExist(err));
} else {
res.status(200).json({
success: true,
message: "success",
token
});
}
});
}
public redirectSocialUser(req, res) {
jwt.sign(helper.buildUserToken(req.user), "secretkey", (tokError, token) => {
if (tokError) {
res.boom.badImplementation(tokError);
} else {
// redirect app to FE app routes with Token
console.log('redirecting Now...');
res.redirect(helper.authRedirectUrl(`?token=${token}`));
/* res.json({
statusCode: 200,
message: "success",
token
}); */
}
});
}
public validate(req: any, res: any) {
res.json({
statusCode: 200,
message: 'validated succsessfully',
success: true,
user : req.user
});
}
/**
* @api {POST} /auth/reset-password update password sent in Mail
* @apiName resetPassword
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
public resetPassword(req, res) {
UserController.resetPassword(req.body.email, (error, success) => {
console.log(error)
if (error) {
res.status(403).json({ success: false, message: error, description: 'error occoured while resetting password' });
} else {
res.json({
statusCode: 200,
message: 'success',
description: 'if this email is registered with us, you will receive a password reset email soon.',
});
}
});
};
public activateUserAccount(req, res) {
UserController.activateUserAccount(req.params.uuid, (error, success) => {
if (error) {
res.status(403).json({ success: false, message: error, description: 'error occoured while activating user' });
} else {
res.redirect(url.FE);
}
});
}
/**
* Take each handler, and attach to one of the Express.Router's
* endpoints.
*/
init() {
this.router.post("/login", expressJoiValidator(expressJoi.loginUser), this.login);
this.router.get("/validate", ValidAuthTokenMiddleware.validateToken, this.validate);
this.router.post("/register", expressJoiValidator(expressJoi.createUser), this.register);
this.router.post("/reset-password", expressJoiValidator(expressJoi.resetPassword), this.resetPassword);
this.router.get("/activate/:uuid", this.activateUserAccount);
/**
* @api {POST} /auth/login/facebook Social Login
* @apiName google
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
/*
this.router.get("/login/facebook", FacebookRoutes.authenticate());
this.router.get(
"/callback/facebook",
FacebookRoutes.callback(),
this.redirectSocialUser
);
*/
/**
* @api {POST} /auth/login/google Social Login
* @apiName google
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
this.router.get("/login/google", GoogleRoutes.authenticate());
this.router.get(
"/callback/google",
GoogleRoutes.callback(),
this.redirectSocialUser
);
/**
* @api {POST} /auth/login/twitter Social Login
* @apiName twitter
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
/*this.router.get("/login/twitter", TwitterRoute.authenticate("twitter"));
this.router.get(
"/callback/twitter",
TwitterRoute.callback(),
this.redirectSocialUser
); */
/**
* @api {POST} /auth/login/linkedin Social Login
* @apiName linkedin
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
/*
this.router.get("/login/likedin", LinkedinRoutes.authenticate());
this.router.get("/login/linkedin", LinkedinRoutes.authenticate());
this.router.get(
"/callback/linkedin",
LinkedinRoutes.callback(),
this.redirectSocialUser
); */
}
}
// Create the HeroRouter, and export its configured Express.Router
const authRoutes = new AuthRouter();
authRoutes.init();
export default authRoutes.router;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/routes/userRoutes.ts
================================================
import * as express from "express";
const router = express.Router();
const passport = require("passport");
import UserController from "../controller/UserController";
const jwt = require("jsonwebtoken");
// seralize user Object
import ResponseTemplate from '../global/templates/response';
import * as expressJoiValidator from "express-joi-validator";
import expressJoi from "../lib/requestValidator";
const boom = require("express-boom");
import { Router } from "express";
const path = require('path')
const fs = require('fs');
const { uploadpath } = global['configuration']
const multer = require('multer');
import Helper from '../helper/bcrypt';
let profileStorage = multer.diskStorage({
destination: function (req, file, cb) {
cb( null, path.join( uploadpath.uploaddir, uploadpath.profiledir ) );
},
filename: function (req, file, cb) {
let extension = Helper.getFileExtension(file.originalname);
cb( null, `${req.user.id}-${ Helper.randomString() }.${extension}` );
}
})
let upload = multer({ storage: profileStorage });
let documentStorage = multer.diskStorage({
destination: function (req, file, cb) {
cb( null, path.join( uploadpath.uploaddir, uploadpath.documentdir ) );
},
filename: function (req, file, cb) {
let extension = Helper.getFileExtension(file.originalname);
cb( null, `${req.user.id}-${ Helper.randomString() }.${extension}` );
}
})
let uploadDocuments = multer({ storage: documentStorage });
export class AuthRouter {
router: Router;
/**
* Initialize the HeroRouter
*/
constructor() {
this.router = Router();
this.init();
}
/**
* @api {POST} /auth/reset-password update password sent in Mail
* @apiName resetPassword
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
public resetPassword(req, res){
UserController.resetPassword( req.body.email, ( error, success) => {
console.log(error)
if ( error ) {
res.status(403).json({success : false, message: error, description: 'error occoured while resetting password' });
} else {
res.json({
statusCode: 200,
message: 'success',
description: 'if this email is registered with us, you will receive a password reset email soon.',
});
}
});
};
public updateUser(req, res){
UserController.updateUser(req.params.email, req.body ,( error, success) => {
if ( error ) {
res.status(403).json({success : false, message: error, description: 'error occoured while updating user' });
} else {
res.json({
statusCode: 200,
message: 'success',
description: 'user updated successfully',
});
}
});
}
public getUserByEmail(req, res){
UserController.getUserByEmail(req.params.email ,( error, user) => {
if ( error ) {
res.status(403).json({success : false, message: error, description: 'error occoured while updating user' });
} else {
res.json({
statusCode: 200,
message: 'success',
data: user
});
}
});
}
public uploadProfilepicture(req, res){
UserController.updateUser( req.user.email, { picture: req.file.filename }, ( error, user ) => {
if ( error ) {
res.json( ResponseTemplate.updateErrorOccoured(error) );
} else {
res.json( ResponseTemplate.success(
'your profile picture has been successfully uploaded',
{ picture: Helper.avatarURL(user.picture) })
);
Helper.deleteFile( 'profile', req.user.picture );
}
});
}
// upload users profile picture.
public uploadDocuments(req, res){
let documents:any = {};
req.files.map( (file) => {
documents.url = file.filename;
documents.originalname = file.originalname;
documents.timestamp = new Date();
});
UserController.updateUser( req.user.email, { document: documents }, ( error, user ) => {
if ( error ) {
res.json( ResponseTemplate.updateErrorOccoured(error) );
} else {
let userDocuments = [];
if ( user.documents ) {
user.documents.map( (doc) => {
userDocuments.push( Helper.userDocumentURL(doc.url) );
});
}
res.json( ResponseTemplate.success(
'host documents have been successfully uploaded',
{ documents: userDocuments })
);
}
});
}
/**
* Take each handler, and attach to one of the Express.Router's
* endpoints.
*/
init() {
this.router.get("/:email", this.getUserByEmail);
this.router.get("/reset-password/:email",expressJoiValidator(expressJoi.resetPassword), this.resetPassword);
this.router.put("/update/:email", this.updateUser);
this.router.post('/upload-profile-picture', upload.single('avatar'), this.uploadProfilepicture);
this.router.post('/upload-documents', uploadDocuments.array('documents'), this.uploadDocuments);
}
}
// Create the HeroRouter, and export its configured Express.Router
const authRoutes = new AuthRouter();
authRoutes.init();
export default authRoutes.router;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/routes.ts
================================================
/* eslint func-names: ["error", "never"] */
/* eslint prefer-destructuring: 0 */
import * as express from 'express';
const expressRouter= express.Router();
import authRoutes from './routes/routes';
import userRoutes from './routes/userRoutes';
import defaultRoutes from './routes/defaultRoutes';
import validAuthTokenMiddleware from './middleware/authMiddleware';
expressRouter.use('/', defaultRoutes);
expressRouter.use('/uploads/', express.static('uploads'));
expressRouter.use('/auth', authRoutes);
expressRouter.use('/user',validAuthTokenMiddleware.validateToken, userRoutes);
export default expressRouter;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/seed/seedUsers.ts
================================================
import User from '../models/user';
const mongoose = require('mongoose');
const dbName = 'blabla';
mongoose.connect(`mongodb://localhost/${dbName}`);
/* eslint quote-props:0 */
/* Aquí vamos a requerir el mongoose, en donde tengo el modelo y la base de datos que creo */
const users = [
{
'username': 'tarun',
'email': 'tarun@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun1222@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun22@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun5@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun1@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun6@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'asdfg@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tgfdsa@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},
{
'username': 'tarun1',
'email': 'tarunfgds8@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},{
'username': 'tarun1',
'email': 'asdfcv@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},{
'username': 'tarun1',
'email': 'dekoo@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},{
'username': 'tarun1',
'email': 'hellodemo@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
},{
'username': 'tarun1',
'email': 'gmail@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 16.5377266,
'lng': 79.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}
];
User.collection.drop();
User.create(users, (err) => {
if (err) {
throw (err);
}
console.log(`Created ${users.length} User`);
mongoose.connection.close();
});
/* Para que se cree esta base de datos tengo que poner en terminal, en otra terminal:
node ./bin/seeds.js. De esta manera se crea la base de datos */
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/seed/seedVehicle.ts
================================================
import User from '../models/user';
const mongoose = require('mongoose');
const dbName = 'blabla';
mongoose.connect(`mongodb://localhost/${dbName}`);
/* eslint quote-props:0 */
/* Aquí vamos a requerir el mongoose, en donde tengo el modelo y la base de datos que creo */
const users = [
{
'username': 'tarun',
'email': 'tarun@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun1222@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun22@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun5@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun1@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun6@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun7@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}, {
'username': 'tarun1',
'email': 'tarun8@gmail.com',
'email_verified': true,
'phone_verified': false,
'gender': null,
'address': 'goa India',
'geo': {
'lat': 15.5377266,
'lng': 73.8316141
},
'password': '$2a$10$S7FH2SqOls7bdAwosDlo0O0fw0wNW7a8e/hF.BqrE.qC9nybWnj0.',
'documents': [],
'status': '1',
'type': '2'
}
];
User.collection.drop();
User.create(users, (err) => {
if (err) {
throw (err);
}
console.log(`Created ${users.length} User`);
mongoose.connection.close();
});
/* Para que se cree esta base de datos tengo que poner en terminal, en otra terminal:
node ./bin/seeds.js. De esta manera se crea la base de datos */
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/transformer/userTransformer.ts
================================================
'use strict';
import _ from 'lodash';
// import ReviewTransformer from './ReviewTransformer';
let UserTransformer = {
xx : (users) =>{
if ( Array.isArray(users) ) {
let output = [];
users.forEach(( user ) => {
output.push( UserTransformer._transformUsers(user) );
});
return output;
}
else {
return UserTransformer._transformUsers(users);
}
},
transform: (users) => {
if (Array.isArray(users)) {
let output = [];
users.forEach((user) => {
output.push(UserTransformer._transform(user));
});
return output;
}
else {
return UserTransformer._transform(users);
}
},
calculateUsers: (users: any | null) => {
if (Array.isArray(users)) {
return {
Users : users.length ? users.length : 100,
vehicles : (users['vehicle'] ) ? users['vehicle'].length : 1000,
cities :100
}
}
},
_transform: (user) => {
if (!user) { return {}; }
let user_status = (user.status === 1) ? 'active' : 'disabled';
return {
id: user._id,
username : user.username,
status: user_status,
name: user.name,
email: user.email,
password: (user.password) ? true : false,
phone: user.phone || '',
gender: user.gender || '',
birthday: user.birthday || '',
type: user.type || 1,
meta: user.meta || {},
social : user.social || [],
phone_verified: user.phone_verified ? true : false,
email_verified: user.email_verified ? true : false,
profile_picture: user.profile_picture ? null : null // will fix later
};
},
transformUsers: ( users ) => {
if ( Array.isArray(users) ) {
let output = [];
users.forEach(( user ) => {
output.push( UserTransformer._transformUsers(user) );
});
return output;
}
else {
return UserTransformer._transformUsers(users);
}
},
_transformUsers: ( user ) => {
if ( ! user ) { return {}; }
let user_status = ( user.status === '1' ) ? 'active' : 'disabled';
const obj:any = {};
return Object.assign({}, {
id: user._id,
username : user.username,
status: user_status,
name: user.name,
email_verified:user.email_verified,
phone_verified :user.phone_verified,
reviews : user.reviews,
vehciles : user.vehciles,
email: user.email,
date : user.createdAt,
type: user.type || 1,
}, obj);
}
}
export default UserTransformer;
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/types/global.d.ts
================================================
declare namespace NodeJS {
export interface Global {
configuration: any
}
}
================================================
FILE: dockerized-containers/e-Commerce-Auth/app/types/vendor.d.ts
================================================
declare namespace NodeJS {
export interface Global {
configuration: any
}
}
================================================
FILE: dockerized-containers/e-Commerce-Auth/env.sh
================================================
# this environment vairables needs to be set in .env file in applciaiton root directory
# copy this file as .env and add the appropriate values as per environment.
# node & mysql
export NODE_ENV="dev"
export PORT="3001"
export MONGO_HOST="ms_commerce_mongo"
export MONGO_PORT="27017"
export MONGO_USERNAME="root"
export MONGO_PASSWORD="root"
export MONGO_DATABASE="ecommerce"
export EXPRESS_SESSION_SECRET="######################"
export F_CLIENTID="###################"
export F_CLIENTSECRET="###########################"
export F_CALLBACK="/auth/callback/facebook"
export G_CLIENTID="@@@@@@@@@@@@@-###############.apps.%%%%%%%%%%%.com"
export G_CLIENTSECRET="k##########@@@@@@@@@@@@Ub"
export G_CALLBACK="/auth/callback/google"
export L_CLIENTID="##################"
export L_CLIENTSECRET="############"
export L_CALLBACK="/auth/callback/linkedin"
export T_CLIENTID="##################"
export T_CLIENTSECRET="######################"
export T_CALLBACK="/auth/callback/twitter"
export FE_URL="localhost:3000"
export API_KEY='XX0xxxxx-xX0X0XxXXxXxXXXxX0x'
export SMTP_HOST='smtp.mandrillapp.com'
export SMTP_PORT='587'
export SMTP_USER='#############.net'
export SMTP_PASSWORD='##############'
export SID='XX0xxxxx-xX0X0XxXXxXxXXXxX0x'
export TOKEN='XX0xxxxx-xX0X0XxXXxXxXXXxX0x'
export PHONE='+9716156786'
export FE='http://localhost:3000'
export API='http://localhost:3005'
export UPLOAD_DIR='uploads'
export PROFILE_PICTURE_DIR='profile'
export DOCUMENT_UPLOAD_DIR='documents'
================================================
FILE: dockerized-containers/e-Commerce-Auth/express.ts
================================================
import router from './app/routes';
import * as boom from 'express-boom';
import * as expressSession from 'express-session';
import * as cookieParser from 'cookie-parser';
import * as passport from 'passport';
import * as helmet from 'helmet';
import * as cors from 'cors';
import * as path from 'path';
import * as express from 'express';
import * as logger from 'morgan';
import * as bodyParser from 'body-parser';
import errorHandlers from './app/helper/errorHandler';
// Creates and configures an ExpressJS web server.
class App {
// ref to Express instance
public express: express.Application;
//Run configuration methods on the Express instance.
constructor() {
this.express = express();
this.middleware();
this.routes();
}
// Configure Express middleware.
private middleware(): void {
this.express.use(passport.initialize());
// required for passport to initlize it
this.express.use(expressSession({ secret: 'bla bla' }));
this.express.use(passport.session());
// initlize session
this.express.use(logger('dev'));
this.express.disable('x-powered-by');
this.express.disable('etag');
this.express.use(helmet());
this.express.use(boom());
this.express.use(helmet.noCache({ noEtag: true })); // set Cache-Control header
this.express.use(helmet.noSniff()); // set X-Content-Type-Options header
this.express.use(helmet.frameguard()); // set X-Frame-Options header
this.express.use(helmet.xssFilter()); // set X-XSS-Protection header
// logger logs on console
this.express.use(bodyParser.urlencoded({ extended: false, limit: '5mb' })); // parse application/x-www-form-urlencoded
this.express.use(bodyParser.json()); // parse application/json
// enable CORS
this.express.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, PUT, PATCH, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, api_key, Authorization, Referer');
next();
});
// register all custom Middleware
this.express.use(cors({ optionsSuccessStatus: 200 }));
this.express.use(cookieParser()); // cookies-parser
// manage session by cookies
this.express.set('views', path.join(__dirname, 'views')); // setting views
this.express.set('view engine', 'hbs');
// server side template rendering
this.express.use(express.static(path.join(__dirname, 'public')));
this.express.use(logger('dev'));
this.express.use(bodyParser.json());
this.express.use(bodyParser.urlencoded({ extended: false }));
}
// Configure API endpoints.
private routes(): void {
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
/* This is just to get up and running, and to make sure what we've got is
* working so far. This function will change when we start to add more
* API endpoints */
this.express.use('/api/v1', router);
this.express.use(errorHandlers.internalServerError);
this.express.use(errorHandlers.PageNotFound);
}
}
export default new App().express;
================================================
FILE: dockerized-containers/e-Commerce-Auth/package.json
================================================
{
"name": "e-commerce-hub",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "cd dist && nodemon server.js",
"prestart": "tsc && cp -r uploads dist/ && cp -r app/global dist/app/",
"startdev": ". ./env.sh && cd dist && nodemon --inspect=0.0.0.0:9201 server.js && tsc --watch",
"clean": "rm -rf dist",
"watch": "tsc",
"copy": "cp -r uploads dist/ && cp -r app/global dist/app/",
"test": ". ./env.sh && NODE_ENV=test && mocha ",
"debug": ". ./env.sh && NODE_ENV=test && cd dist && nodemon server.js",
"prestartdev": " npm run clean && tsc && npm run copy && npm run watch",
"poststartdev": "tsc --watch",
"watchserver": "tsc --watch",
"dev": ". ./env.sh && ts-node server.ts",
"start-tsc": ". ./env.sh && nodemon ./dist/server.js",
"buildAndstart": ". ./env.sh && npm run build && npm run start"
},
"dependencies": {
"@types/express": "^4.11.1",
"assert": "^1.4.1",
"axios": "^0.18.0",
"bcrypt-nodejs": "0.0.3",
"bluebird": "^3.5.3",
"body-parser": "^1.18.3",
"cookie-parser": "^1.4.3",
"cors": "^2.8.5",
"dotenv": "^6.1.0",
"email-templates": "^2.7.1",
"express": "^4.16.4",
"express-boom": "^2.0.0",
"express-joi-validator": "^2.0.0",
"express-session": "^1.15.6",
"fast-csv": "^2.4.1",
"hbs": "^4.0.1",
"helmet": "^3.15.0",
"joi": "^14.1.1",
"jsonwebtoken": "^8.4.0",
"mocha": "^5.2.0",
"moment": "^2.22.2",
"mongoose": "^4.5.9",
"morgan": "^1.9.0",
"multer": "^1.2.0",
"nodemailer": "2.5.0",
"nodemon": "^1.18.6",
"passport": "0.3.2",
"passport-facebook": "2.1.1",
"passport-google-oauth": "1.0.0",
"passport-google-oauth20": "^1.0.0",
"passport-instagram": "1.0.0",
"passport-linkedin": "^1.0.0",
"passport-local": "1.0.0",
"passport-twitter": "1.0.4",
"pug": "2.0.0-beta6",
"serve-favicon": "^2.5.0",
"ts-lint": "^4.5.1",
"ts-node": "^7.0.1",
"twilio": "^2.11.1",
"typescript": "^3.1.6",
"uuid": "^3.3.2",
"winston": "^2.4.2"
},
"devDependencies": {
"@types/async": "^2.0.45",
"@types/bcrypt-nodejs": "^0.0.30",
"@types/bluebird": "^3.5.20",
"@types/body-parser": "^1.16.8",
"@types/express": "^4.11.1",
"@types/mongoose": "^4.7.34",
"@types/morgan": "^1.7.35",
"@types/node": "^9.6.39",
"@types/nodemailer": "^4.3.4",
"@types/passport": "^0.4.3",
"babel-eslint": "^8.0.1",
"eslint": "^4.19.1",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-node": "^5.2.1"
}
}
================================================
FILE: dockerized-containers/e-Commerce-Auth/public/javascripts/script.js
================================================
document.addEventListener('DOMContentLoaded', () => {
console.log('IronGenerator JS imported successfully!');
}, false);
================================================
FILE: dockerized-containers/e-Commerce-Auth/public/style.scss
================================================
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}
.h1 {
font-size: 40px;
}
================================================
FILE: dockerized-containers/e-Commerce-Auth/server.ts
================================================
import * as http from 'http';
import * as debug from 'debug';
// After you declare "app"
const env = process.env.NODE_ENV || 'dev'
console.log(` using ${process.env.NODE_ENV} to run application`);
global.configuration = require(`./app/config/environments/${env}`);
import App from './express';
const port = (process.env.PORT);
const logger = require('winston');
import mongoose from './app/lib/mongoose';
mongoose();
const server = http.createServer(App);
server.listen(process.env.PORT);
server.on('error', onError);
server.on('listening', onListening);
function onError(error: NodeJS.ErrnoException): void {
if (error.syscall !== 'listen') throw error;
let bind = (typeof port === 'string') ? 'Pipe ' + port : 'Port ' + port;
switch(error.code) {
case 'EACCES':
console.error(`${bind} requires elevated privileges`);
process.exit(1);
break;
case 'EADDRINUSE':
console.error(`${bind} is already in use`);
process.exit(1);
break;
default:
throw error;
}
}
const gracefulStopServer = function () {
// Wait 10 secs for existing connection to close and then exit.
setTimeout(() => {
logger.info('Shutting down server');
process.exit(0);
}, 1000);
};
process.on('uncaughtException', (err) => {
logger.error(err, 'Uncaught exception');
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
logger.error({
promise,
reason
}, 'unhandledRejection');
process.exit(1);
});
process.on('SIGINT', gracefulStopServer);
process.on('SIGTERM', gracefulStopServer);
function onListening(): void {
let addr = server.address();
let bind = (typeof addr === 'string') ? `pipe ${addr}` : `port ${addr.port}`;
console.log(`Listening on ${bind}`);
}
================================================
FILE: dockerized-containers/e-Commerce-Auth/tsconfig.json
================================================
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"pretty": true,
"sourceMap": true,
"target": "es6",
"outDir": "./dist",
"experimentalDecorators": false,
"emitDecoratorMetadata": false,
"skipDefaultLibCheck": false,
"baseUrl": "./lib"
},
"files" : [
"./app/types/vendor.d.ts"
],
"include": [
"/**/*.ts"
],
"exclude": [
"node_modules"
]
}
================================================
FILE: dockerized-containers/e-Commerce-Auth/tslint.json
================================================
================================================
FILE: dockerized-containers/e-Commerce-Auth/uploads/documents/.gitkeep
================================================
================================================
FILE: dockerized-containers/e-Commerce-Auth/uploads/profile/.gitkeep
================================================
================================================
FILE: dockerized-containers/e-Commerce-Cart/.sequelizerc
================================================
const path = require('path');
module.exports = {
'config': path.resolve('config', 'config.js')
}
================================================
FILE: dockerized-containers/e-Commerce-Cart/Dockerfile
================================================
FROM node:carbon
# Create app directory
WORKDIR /usr/src/app
# Bundle app source
COPY . .
# npm install
RUN npm install
# Run npm install --global grpc --unsafe-perm
EXPOSE 3004 9204
CMD [ "npm", "run", "watchserver" ]
CMD [ "npm", "run", "startdev" ]
================================================
FILE: dockerized-containers/e-Commerce-Cart/README.md
================================================
# Application for e-commerce Hub
REST API to support application features
- Express as web framework with Typescript
- Passport js for social authentication
- Express CORS enabled
- boom for error codes & Joi for Validation
- Winston for logging and express minitor for monitoring
- Mongoose as ODM driver
- eslint validation extending airbnb styleguide
- git hooks & CI/CD in place
- Typescript based compilation tsc compiler
- TDD in progress with Mocha
- JWT based authentication
- multiple Mongoose collection with referencing
- payment gateway Integration
- Heroku deployment
- Mini e-commerce platform
# Cart Application #
"It's just simple application to provide REST APIs for mini e-commerce platform where individual can buy products and can pay the bills
```
# Application Execution
```javascript
git clone repo
npm install
npm run startdev
tsc -- watch
```
# Application configuration
```javascript
env.sh need to be added locally
export NODE_ENV="dev"
export PORT="3005"
export MONGOURL="mongodb://mongo/hello"
export EXPRESS_SESSION_SECRET="************************"
export F_CLIENTID="**************"
export F_CLIENTSECRET="**********************"
```
# Application NPM Script
```javascript
"start": "cd dist && nodemon server.js",
"prestart": "tsc && cp -r uploads dist/ && cp -r app/global dist/app/",
"clean" : "rm -rf dist",
"copy" : "cp -r uploads dist/ && cp -r app/global dist/app/"
```
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/config/environments/dev.ts
================================================
/* eslint quote-props: 0 */
export { }
const configuration: any = {};
configuration.mongo = {
url: process.env.MONGODB_URI || process.env.MONGOURL,
};
configuration.URL = {
frontEnd: process.env.FE_URL
}
configuration.db = {
user: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
connectTimeout: 80000,
};
configuration.facebook = {
client_id: process.env.F_CLIENTID,
client_secret: process.env.F_CLIENTSECRET,
callback_url: process.env.F_CALLBACK
};
configuration.google = {
client_id: process.env.G_CLIENTID,
client_secret: process.env.G_CLIENTSECRET,
callback_url: process.env.G_CALLBACK
};
configuration.linkedin = {
client_id: process.env.L_CLIENTID,
client_secret: process.env.L_CLIENTSECRET,
callback_url: process.env.L_CALLBACK
};
configuration.twitter = {
client_id: process.env.T_CLIENTID,
client_secret: process.env.T_CLIENTSECRET,
callback_url: process.env.T_CALLBACK
};
configuration.email = {
apiKey: process.env.API_KEY,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
}
}
configuration.twilio = {
sid: process.env.SID,
token: process.env.TOKEN,
phone: process.env.PHONE,
}
configuration.url = {
FE: process.env.FE,
API: process.env.API,
}
configuration.uploadpath = {
uploaddir: process.env.UPLOAD_DIR,
profiledir: process.env.PROFILE_PICTURE_DIR
}
configuration.logLevel ='info';
module.exports = configuration;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/config/environments/qa.ts
================================================
/* eslint quote-props: 0 */
export { }
const configuration: any = {};
configuration.mongo = {
url: process.env.MONGODB_URI || process.env.MONGOURL,
};
configuration.URL = {
frontEnd: process.env.FE_URL
}
configuration.db = {
user: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
connectTimeout: 80000,
};
configuration.facebook = {
client_id: process.env.F_CLIENTID,
client_secret: process.env.F_CLIENTSECRET,
callback_url: process.env.F_CALLBACK
};
configuration.google = {
client_id: process.env.G_CLIENTID,
client_secret: process.env.G_CLIENTSECRET,
callback_url: process.env.G_CALLBACK
};
configuration.linkedin = {
client_id: process.env.L_CLIENTID,
client_secret: process.env.L_CLIENTSECRET,
callback_url: process.env.L_CALLBACK
};
configuration.twitter = {
client_id: process.env.T_CLIENTID,
client_secret: process.env.T_CLIENTSECRET,
callback_url: process.env.T_CALLBACK
};
configuration.email = {
apiKey: process.env.API_KEY,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
}
}
configuration.twilio = {
sid: process.env.SID,
token: process.env.TOKEN,
phone: process.env.PHONE,
}
configuration.url = {
FE: process.env.FE,
API: process.env.API,
}
configuration.uploadpath = {
uploaddir: process.env.UPLOAD_DIR,
profiledir: process.env.PROFILE_PICTURE_DIR
}
configuration.logLevel ='info';
module.exports = configuration;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/config/environments/test.ts
================================================
/* eslint quote-props: 0 */
export { }
const configuration: any = {};
configuration.mongo = {
url: process.env.MONGODB_URI || process.env.MONGOURL,
};
configuration.URL = {
frontEnd: process.env.FE_URL
}
configuration.db = {
user: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
connectTimeout: 80000,
};
configuration.facebook = {
client_id: process.env.F_CLIENTID,
client_secret: process.env.F_CLIENTSECRET,
callback_url: process.env.F_CALLBACK
};
configuration.google = {
client_id: process.env.G_CLIENTID,
client_secret: process.env.G_CLIENTSECRET,
callback_url: process.env.G_CALLBACK
};
configuration.linkedin = {
client_id: process.env.L_CLIENTID,
client_secret: process.env.L_CLIENTSECRET,
callback_url: process.env.L_CALLBACK
};
configuration.twitter = {
client_id: process.env.T_CLIENTID,
client_secret: process.env.T_CLIENTSECRET,
callback_url: process.env.T_CALLBACK
};
configuration.email = {
apiKey: process.env.API_KEY,
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASSWORD,
}
}
configuration.twilio = {
sid: process.env.SID,
token: process.env.TOKEN,
phone: process.env.PHONE,
}
configuration.url = {
FE: process.env.FE,
API: process.env.API,
}
configuration.uploadpath = {
uploaddir: process.env.UPLOAD_DIR,
profiledir: process.env.PROFILE_PICTURE_DIR
}
configuration.logLevel ='info';
module.exports = configuration;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/events/processEvent.ts
================================================
const events = require('events');
const eventEmitter = new events.EventEmitter();
export default eventEmitter;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/helper/errorHandler.ts
================================================
import logger from '../lib/logger';
import ResponseTemplate from './responseTemplate';
/* eslint class-methods-use-this:0 */
const env = process.env.NODE_ENV;
const onDevEnv = env === 'dev' || env === 'test' || env === 'local';
class errorHandler {
public internalServerError(err, req, res, next) {
logger.log('info',err);
if (err.isBoom) {
// Error From joi express validator
const error = {
message: err.output.payload.error,
error: err.output.payload.message
};
res.status(400).json(ResponseTemplate.BadRequestFromJoi(error));
} else { // internalServerError
res.status(500).json({
success: false,
message: err.message,
error: (onDevEnv) ? err.stack : {}
});
}
}
public PageNotFound(req, res, err) {
res.status(404).json({ message: 'api not found' });
}
}
export default new errorHandler();
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/helper/errors.ts
================================================
class APIError extends Error {
constructor(message, ErrorID, code = null) {
super();
Error.captureStackTrace(this, this.constructor);
this.name = 'api error';
this.message = message;
if (ErrorID) this['ErrorID'] = ErrorID;
if (code) this['code'] = code;
}
}
export default APIError;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/helper/logger.ts
================================================
const log = require('loglevel');
log.setLevel(global.configuration.logLevel);
const logger = log;
export default logger;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/helper/responseTemplate.ts
================================================
/* istanbul ignore file */
const data: any = {
general(data) {
return data;
},
successMessage(message) {
return {
success: true,
message
};
},
success(data, message) {
return {
success: true,
message,
data
};
},
error(message, err, code= null) {
return {
success: false,
message: message || 'some error occurred',
error: err || 'error occurred on server, please try again after some time.'
};
},
emptyContent() {
return this.general({
message: 'empty content found',
description: 'you must provide valid data and it must not be empty.',
helpful_links: ['http://stackoverflow.com/questions/18419428/what-is-the-minimum-valid-json']
});
},
invalidContentType() {
return this.general({
message: 'invalid content type',
description: 'you must specify content type and it must be application/json',
helpful_links: ['http://stackoverflow.com/questions/477816/what-is-the-correct-json-content-type']
});
},
BadRequestFromJoi(err) {
return this.error(
err.message,
err.error
);
},
userAlreadyExist(err) {
return this.general({
success: false,
message: 'user already registered in System',
description: 'user already registered in System'
});
},
userdoesNotExist(err) {
return this.general({
success: false,
message: err.message || 'user not registered in system',
description: 'user account does not exist in system'
});
},
commonAuthUserDataError() {
return this.error(
'Authentication error',
'token verification failed, Please try again'
);
},
tokenRequiredAuthError() {
return this.error(
'Authentication error, Token is required in Header',
'token verification failed, Please try again'
);
},
};
export default data;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/lib/logger.ts
================================================
const log = require('loglevel');
log.setLevel(global.configuration.logLevel);
const logger = log;
export default logger;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/lib/mysql.ts
================================================
import APIError from '../helper/errors';
import logger from './logger';
const mysql = require('mysql2');
import eventEmitter from '../events/processEvent';
/* eslint func-names: ["error", "never"] */
const config = global['configuration'].db;
console.log(config);
let connection:any = null;
try {
connection = mysql.createConnection(config);
} catch (err) {
logger.error('Cannot establish a connection with the database');
/** To Prevent sensitive info leak, not raising actual error */
throw new APIError('Mysql connection failed (config)', 1);
}
connection.connect((err) => {
// in case of error
if (err) throw new APIError('Mysql connection failed (connect)', 1);
else {
logger.info(`MysqlClient connected to port ${config.port || 3306} and ${config.host} host`);
eventEmitter.emit('dbReady', connection);
}
});
connection.on('error', (err) => {
logger.error('Cannot establish a connection with the database');
/** To Prevent sensitive info leak, not raising actual error */
throw new APIError('Mysql connection failed (event)', 1);
});
export default connection;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/lib/requestValidator.ts
================================================
const Joi = require('joi');
const validation = {
loginUser : {
body : {
email: Joi.string().regex(/^[\w.]+@[\w]+?(\.[a-zA-Z]{2,3}){1,3}$/).required(),
password: Joi.string().min(8).max(50).required()
}
},
createUser: {
body: {
username: Joi.string().min(4).max(50).required(),
password: Joi.string().min(8).max(50).required(),
email: Joi.string().regex(/^[\w.]+@[\w]+?(\.[a-zA-Z]{2,3}){1,3}$/).required(),
verify_password: Joi.string().min(6).max(50).required()
},
},
resetPassword: {
body: {
email: Joi.string().regex(/^[\w.]+@[\w]+?(\.[a-zA-Z]{2,3}){1,3}$/).required(),
}
}
};
export default validation
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/middleware/requestValidator.ts
================================================
module.exports = {
validatePayload(req, res, next) {
// validatr token here is its valid here
const token = req.body;
if ((req.method === 'POST' || req.method === 'PUT') && req.body !== null) {
next();
}
res.status(403).json({ message: 'payload is required for HTTP Post & Put ' });
}
};
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/models/data/cart.ts
================================================
const Product= {
products: [
{
availableSizes: [
"S",
"XS"
],
currencyFormat: "$",
currencyId: "USD",
description: "4 MSL",
id: 12,
installments: 9,
isFreeShipping: true,
price: 10.9,
sku: 12064273040195392,
style: "Black with custom print",
title: "Cat Tee Black T-Shirt"
},
{
availableSizes: [
"M"
],
currencyFormat: "$",
currencyId: "USD",
description: "",
id: 13,
installments: 5,
isFreeShipping: true,
price: 29.45,
sku: 51498472915966370,
style: "Front print and paisley print",
title: "Dark Thug Blue-Navy T-Shirt"
},
{
availableSizes: [
"X",
"L",
"XL"
],
currencyFormat: "$",
currencyId: "USD",
description: "GPX Poly 1",
id: 14,
installments: 3,
isFreeShipping: true,
price: 9,
sku: 10686354557628304,
style: "Front tie dye print",
title: "Sphynx Tie Dye Wine T-Shirt"
},
{
availableSizes: [
"X",
"L",
"XL",
"XXL"
],
currencyFormat: "$",
currencyId: "USD",
description: "Treino 2014",
id: 15,
installments: 5,
isFreeShipping: true,
price: 14,
sku: 11033926921508488,
style: "Black T-Shirt with front print",
title: "Skuul"
},
{
availableSizes: [
"X",
"L"
],
currencyFormat: "$",
currencyId: "USD",
description: "",
id: 11,
installments: 3,
isFreeShipping: true,
price: 13.25,
sku: 39876704341265610,
style: "Wine",
title: "Wine Skul T-Shirt"
},
{
availableSizes: [
"X",
"L",
"XL",
"XXL"
],
currencyFormat: "$",
currencyId: "USD",
description: "14/15 s/nº",
id: 0,
installments: 9,
isFreeShipping: true,
price: 10.9,
sku: 8552515751438644,
style: "Branco com listras pretas",
title: "Cat Tee Black T-Shirt"
},
{
availableSizes: [
"X",
"L",
"XL",
"XXL"
],
currencyFormat: "$",
currencyId: "USD",
description: "14/15 s/nº",
id: 1,
installments: 9,
isFreeShipping: true,
price: 10.9,
sku: 18644119330491310,
style: "Preta com listras brancas",
title: "Sphynx Tie Dye Grey T-Shirt"
},
{
availableSizes: [
"X",
"L"
],
currencyFormat: "$",
currencyId: "USD",
description: "14/15 s/nº",
id: 2,
installments: 7,
isFreeShipping: true,
price: 14.9,
sku: 11854078013954528,
style: "Branco com listras pretas",
title: "Danger Knife Grey"
},
{
availableSizes: [
"X",
"L"
],
currencyFormat: "$",
currencyId: "USD",
description: "2014 s/nº",
id: 3,
installments: 7,
isFreeShipping: true,
price: 14.9,
sku: 876661122392077,
style: "Preto com listras brancas",
title: "White DGK Script Tee"
},
{
availableSizes: [
"XL"
],
currencyFormat: "$",
currencyId: "USD",
description: "14/15 s/nº - Jogador",
id: 4,
installments: 12,
isFreeShipping: false,
price: 25.9,
sku: 9197907543445676,
style: "Branco com listras pretas",
title: "Born On The Streets"
},
{
availableSizes: [
"X",
"L",
"XL"
],
currencyFormat: "$",
currencyId: "USD",
description: "14/15 + Camiseta 1º Mundial",
id: 5,
installments: 9,
isFreeShipping: false,
price: 10.9,
sku: 10547961582846888,
style: "Preto",
title: "Tso 3D Short Sleeve T-Shirt A"
},
{
availableSizes: [
"XL",
"XXL"
],
currencyFormat: "$",
currencyId: "USD",
description: "Goleiro 13/14",
id: 6,
installments: 0,
isFreeShipping: true,
price: 49.9,
sku: 6090484789343891,
style: "Branco",
title: "Man Tie Dye Cinza Grey T-Shirt"
},
{
availableSizes: [
"S"
],
currencyFormat: "$",
currencyId: "USD",
description: "1977 Infantil",
id: 7,
installments: 4,
isFreeShipping: true,
price: 22.5,
sku: 18532669286405344,
style: "Preto com listras brancas",
title: "Crazy Monkey Black T-Shirt"
},
{
availableSizes: [
"XL"
],
currencyFormat: "$",
currencyId: "USD",
description: "",
id: 8,
installments: 4,
isFreeShipping: false,
price: 18.7,
sku: 5619496040738316,
style: "Azul escuro",
title: "Tso 3D Black T-Shirt"
},
{
availableSizes: [
"L",
"XL"
],
currencyFormat: "$",
currencyId: "USD",
description: "",
id: 9,
installments: 5,
isFreeShipping: true,
price: 134.9,
sku: 11600983276356164,
style: "",
title: "Crazy Monkey Grey"
},
{
availableSizes: [
"L",
"XL"
],
currencyFormat: "$",
currencyId: "USD",
description: "",
id: 10,
installments: 9,
isFreeShipping: true,
price: 49,
sku: 27250082398145996,
style: "",
title: "On The Streets Black T-Shirt"
}
]
};
export default Product;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/routes/defaultRoutes.ts
================================================
import * as express from "express";
const router = express.Router();
import { Router } from "express";
import product from '../models/data/cart';
export class DefaultRouter {
router: Router;
/**
* Initialize the HeroRouter
*/
constructor() {
this.router = Router();
}
/**
* @api {POST} /auth/reset-password update password sent in Mail
* @apiName resetPassword
* @apiGroup Auth
* @apiSuccess {String} code HTTP status code from API.
* @apiSuccess {String} message Message from API.
*/
public sayHello(req, res) {
res.status(200).json({ success: true, message: 'i am up and running with mysql + node .. ⚡️⚡️⚡️⚡️⚡️⚡️⚡️' });
};
public getProducts(req, res) {
res.status(200).json(product);
};
init() {
this.router.get("/", this.sayHello);
this.router.get("/products", this.getProducts);
}
}
// Create the HeroRouter, and export its configured Express.Router
const defaultRouter = new DefaultRouter();
defaultRouter.init();
export default defaultRouter.router;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/routes.ts
================================================
/* eslint func-names: ["error", "never"] */
/* eslint prefer-destructuring: 0 */
import * as express from 'express';
const expressRouter= express.Router();
import defaultRoutes from './routes/defaultRoutes';
expressRouter.use('/', defaultRoutes);
export default expressRouter;
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/types/global.d.ts
================================================
declare namespace NodeJS {
export interface Global {
configuration: any
}
}
================================================
FILE: dockerized-containers/e-Commerce-Cart/app/types/vendor.d.ts
================================================
declare namespace NodeJS {
export interface Global {
configuration: any
}
}
================================================
FILE: dockerized-containers/e-Commerce-Cart/config/config.js
================================================
const fs = require('fs');
module.exports = {
local: {
username: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
dialect: 'mysql'
},
dev: {
username: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
dialect: 'mysql'
},
test: {
username: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
dialect: 'mysql'
},
qa: {
username: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
dialect: 'mysql'
},
uat: {
username: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
dialect: 'mysql'
},
prod: {
username: process.env.USERNAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
host: process.env.HOST,
dialect: 'mysql'
}
};
================================================
FILE: dockerized-containers/e-Commerce-Cart/env.sh
================================================
# this environment vairables needs to be set in .env file in applciaiton root directory
# copy this file as .env and add the appropriate values as per environment.
# node & mysql
export NODE_ENV="dev"
export PORT="3004"
export USERNAME="root"
export PASSWORD="root"
export DATABASE="cartDB"
export HOST="mysql"
================================================
FILE: dockerized-containers/e-Commerce-Cart/express.ts
================================================
import router from './app/routes';
import * as boom from 'express-boom';
import * as expressSession from 'express-session';
import * as cookieParser from 'cookie-parser';
import * as passport from 'passport';
import * as helmet from 'helmet';
import * as cors from 'cors';
import * as path from 'path';
import * as express from 'express';
import * as logger from 'morgan';
import * as bodyParser from 'body-parser';
import errorHandlers from './app/helper/errorHandler';
// Creates and configures an ExpressJS web server.
class App {
// ref to Express instance
public express: express.Application;
//Run configuration methods on the Express instance.
constructor() {
this.express = express();
this.middleware();
this.routes();
}
// Configure Express middleware.
private middleware(): void {
this.express.use(passport.initialize());
// required for passport to initlize it
this.express.use(expressSession({ secret: 'bla bla' }));
this.express.use(passport.session());
// initlize session
this.express.use(logger('dev'));
this.express.disable('x-powered-by');
this.express.disable('etag');
this.express.use(helmet());
this.express.use(boom());
this.express.use(helmet.noCache({ noEtag: true })); // set Cache-Control header
this.express.use(helmet.noSniff()); // set X-Content-Type-Options header
this.express.use(helmet.frameguard()); // set X-Frame-Options header
this.express.use(helmet.xssFilter()); // set X-XSS-Protection header
// logger logs on console
this.express.use(bodyParser.urlencoded({ extended: false, limit: '5mb' })); // parse application/x-www-form-urlencoded
this.express.use(bodyParser.json()); // parse application/json
// enable CORS
this.express.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, PUT, PATCH, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, api_key, Authorization, Referer');
next();
});
// register all custom Middleware
this.express.use(cors({ optionsSuccessStatus: 200 }));
this.express.use(cookieParser()); // cookies-parser
// manage session by cookies
this.express.set('views', path.join(__dirname, 'views')); // setting views
this.express.set('view engine', 'hbs');
// server side template rendering
this.express.use(express.static(path.join(__dirname, 'public')));
this.express.use(logger('dev'));
this.express.use(bodyParser.json());
this.express.use(bodyParser.urlencoded({ extended: false }));
}
// Configure API endpoints.
private routes(): void {
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
/* This is just to get up and running, and to make sure what we've got is
* working so far. This function will change when we start to add more
* API endpoints */
this.express.use('/api/v1', router);
this.express.use(errorHandlers.internalServerError);
this.express.use(errorHandlers.PageNotFound);
}
}
export default new App().express;
================================================
FILE: dockerized-containers/e-Commerce-Cart/mysql/schema.sql
================================================
CREATE DATABASE IF NOT EXISTS `shopping_cart_db` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `shopping_cart_db`;
DROP TABLE IF EXISTS `carts`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `carts` (
`idcarts` bigint(20) NOT NULL,
`idcustomer` bigint(20) NOT NULL,
`subtotal` decimal(10,2) NOT NULL,
PRIMARY KEY (`idcarts`),
KEY `carts_customers_fk_idx` (`idcustomer`),
CONSTRAINT `carts_customers_fk` FOREIGN KEY (`idcustomer`) REFERENCES `customers` (`idcustomer`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `categories`
--
DROP TABLE IF EXISTS `categories`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `categories` (
`idcategory` int(11) NOT NULL AUTO_INCREMENT,
`description` varchar(20) NOT NULL,
PRIMARY KEY (`idcategory`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 PACK_KEYS=0;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `customers`
--
DROP TABLE IF EXISTS `customers`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `customers` (
`idcustomer` bigint(20) NOT NULL AUTO_INCREMENT,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`username` varchar(50) NOT NULL,
`password` varchar(256) NOT NULL,
PRIMARY KEY (`idcustomer`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `lines_item`
--
DROP TABLE IF EXISTS `lines_item`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `lines_item` (
`idlines_item` bigint(20) NOT NULL AUTO_INCREMENT,
`idorder` bigint(20) DEFAULT NULL,
`idproduct` bigint(20) NOT NULL,
`quantity` int(11) NOT NULL,
`price` decimal(10,2) NOT NULL,
`idcart` bigint(20) NOT NULL,
PRIMARY KEY (`idlines_item`),
KEY `lines_item_orders_fk_idx` (`idorder`),
KEY `lines_item_products_fk_idx` (`idproduct`),
KEY `lines_item_carts_fk_idx` (`idcart`),
CONSTRAINT `lines_item_orders_fk` FOREIGN KEY (`idorder`) REFERENCES `orders` (`idcustomer`) ON UPDATE CASCADE,
CONSTRAINT `lines_item_carts_fk` FOREIGN KEY (`idcart`) REFERENCES `carts` (`idcarts`) ON UPDATE CASCADE,
CONSTRAINT `lines_item_products_fk` FOREIGN KEY (`idproduct`) REFERENCES `products` (`idproduct`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `orders`
--
DROP TABLE IF EXISTS `orders`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `orders` (
`idorder` bigint(20) NOT NULL AUTO_INCREMENT,
`ordered` datetime NOT NULL,
`status` varchar(20) NOT NULL,
`idcustomer` bigint(20) NOT NULL,
`total` decimal(10,2) NOT NULL,
PRIMARY KEY (`idorder`),
KEY `orders_customers_fk_idx` (`idcustomer`),
CONSTRAINT `orders_customers_fk` FOREIGN KEY (`idcustomer`) REFERENCES `customers` (`idcustomer`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `products`
--
DROP TABLE IF EXISTS `products`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `products` (
`idproduct` bigint(20) NOT NULL AUTO_INCREMENT,
`description` varchar(100) NOT NULL,
`price` decimal(10,2) NOT NULL,
`idcategory` int(11) DEFAULT NULL,
PRIMARY KEY (`idproduct`),
KEY `products_categories_fk` (`idcategory`),
CONSTRAINT `products_categories_fk` FOREIGN KEY (`idcategory`) REFERENCES `categories` (`idcategory`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
================================================
FILE: dockerized-containers/e-Commerce-Cart/package.json
================================================
{
"name": "e-commerce-hub",
"version": "0.0.0",
"private": true,
"scripts": {
"start:local": " . ./env.sh && NODE_ENV=local nodemon app/server.js ",
"create:local": ". ./env.sh && NODE_ENV=local ./node_modules/.bin/sequelize db:create",
"migrate:local": ". ./env.sh && NODE_ENV=local ./node_modules/.bin/sequelize db:migrate",
"seed:local": " . ./env.sh && NODE_ENV=local ./node_modules/.bin/sequelize db:migrate --migrations-path seeders",
"start": "cd dist && nodemon server.js",
"prestart": "tsc && cp -r uploads dist/ && cp -r app/global dist/app/",
"startdev": ". ./env.sh && cd dist && nodemon server.js",
"clean": "rm -rf dist",
"watch": "tsc",
"copy": "cp -r uploads dist/ && cp -r app/global dist/app/",
"test": ". ./env.sh && NODE_ENV=test && mocha ",
"debug": ". ./env.sh && NODE_ENV=test && cd dist && nodemon --inspect=0.0.0.0:9230 server.js",
"prestartdev": " npm run clean && tsc && npm run copy && npm run watch",
"poststartdev": "tsc --watch",
"watchserver": "tsc --watch",
"dev": ". ./env.sh && ts-node server.ts",
"start-tsc": ". ./env.sh && nodemon ./dist/server.js",
"buildAndstart": ". ./env.sh && npm run build && npm run start"
},
"dependencies": {
"@types/express": "^4.11.1",
"assert": "^1.4.1",
"axios": "^0.18.0",
"bcrypt-nodejs": "0.0.3",
"bluebird": "^3.5.3",
"body-parser": "^1.18.3",
"cookie-parser": "^1.4.3",
"cors": "^2.8.5",
"dotenv": "^6.1.0",
"email-templates": "^2.7.1",
"express": "^4.16.4",
"express-boom": "^2.0.0",
"express-joi-validator": "^2.0.0",
"express-session": "^1.15.6",
"fast-csv": "^2.4.1",
"hbs": "^4.0.1",
"helmet": "^3.15.0",
"joi": "^14.1.1",
"jsonwebtoken": "^8.4.0",
"loglevel": "^1.6.1",
"mocha": "^5.2.0",
"moment": "^2.22.2",
"mongoose": "^4.5.9",
"morgan": "^1.9.0",
"multer": "^1.2.0",
"mysql2": "^1.6.5",
"nodemailer": "2.5.0",
"nodemon": "^1.18.6",
"passport": "0.3.2",
"passport-facebook": "2.1.1",
"passport-google-oauth": "1.0.0",
"passport-google-oauth20": "^1.0.0",
"passport-instagram": "1.0.0",
"passport-linkedin": "^1.0.0",
"passport-local": "1.0.0",
"passport-twitter": "1.0.4",
"pug": "2.0.0-beta6",
"sequelize": "^4.37.4",
"sequelize-cli": "^4.0.0",
"serve-favicon": "^2.5.0",
"ts-lint": "^4.5.1",
"ts-node": "^7.0.1",
"twilio": "^2.11.1",
"typescript": "^3.1.6",
"uuid": "^3.3.2"
},
"devDependencies": {
"@types/async": "^2.0.45",
"@types/bcrypt-nodejs": "^0.0.30",
"@types/bluebird": "^3.5.20",
"@types/body-parser": "^1.16.8",
"@types/express": "^4.11.1",
"@types/mongoose": "^4.7.34",
"@types/morgan": "^1.7.35",
"@types/node": "^9.6.39",
"@types/nodemailer": "^4.3.4",
"@types/passport": "^0.4.3",
"babel-eslint": "^8.0.1",
"eslint": "^4.19.1",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-node": "^5.2.1"
}
}
================================================
FILE: dockerized-containers/e-Commerce-Cart/public/javascripts/script.js
================================================
document.addEventListener('DOMContentLoaded', () => {
console.log('IronGenerator JS imported successfully!');
}, false);
================================================
FILE: dockerized-containers/e-Commerce-Cart/public/style.scss
================================================
body {
padding: 50px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}
.h1 {
font-size: 40px;
}
================================================
FILE: dockerized-containers/e-Commerce-Cart/server.ts
================================================
import * as http from 'http';
import * as debug from 'debug';
// After you declare "app"
const env = process.env.NODE_ENV || 'dev'
console.log(` using ${process.env.NODE_ENV} to run application`);
global.configuration = require(`./app/config/environments/${env}`);
import App from './express';
import eventEmitter from './app/events/processEvent'
const port = (process.env.PORT);
import logger from './app/lib/logger';
import mysql from './app/lib/mysql';
global['connection'] = mysql
const appServer = http.createServer(App);
appServer.on('error', onError);
appServer.on('listening', onListening);
if (!module.parent) {
eventEmitter.on('dbReady', (connection) => {
const port = process.env.PORT;
appServer.listen(process.env.PORT,
() => {
logger.info(`API running in environment ${process.env.NODE_ENV}`);
logger.info(`API running at http://localhost:${port}`);
},
);
appServer.setTimeout(200000);
if (process['parent']) process.send('ready');
});
}
function onError(error: NodeJS.ErrnoException): void {
if (error.syscall !== 'listen') throw error;
let bind = (typeof port === 'string') ? 'Pipe ' + port : 'Port ' + port;
switch(error.code) {
case 'EACCES':
console.error(`${bind} requires elevated privileges`);
process.exit(1);
break;
case 'EADDRINUSE':
console.error(`${bind} is already in use`);
process.exit(1);
break;
default:
throw error;
}
}
const gracefulStopServer = function () {
// Wait 10 secs for existing connection to close and then exit.
setTimeout(() => {
logger.info('Shutting down server');
process.exit(0);
}, 1000);
};
process.on('uncaughtException', (err) => {
logger.error(err, 'Uncaught exception');
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
logger.error({
promise,
reason
}, 'unhandledRejection');
process.exit(1);
});
process.on('SIGINT', gracefulStopServer);
process.on('SIGTERM', gracefulStopServer);
function onListening(): void {
let addr = appServer.address();
let bind = (typeof addr === 'string') ? `pipe ${addr}` : `port ${addr.port}`;
debug(`Listening on ${bind}`);
}
================================================
FILE: dockerized-containers/e-Commerce-Cart/tsconfig.json
================================================
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"pretty": true,
"sourceMap": true,
"target": "es6",
"outDir": "./dist",
"experimentalDecorators": false,
"emitDecoratorMetadata": false,
"skipDefaultLibCheck": false,
"baseUrl": "./lib"
},
"files" : [
"./app/types/vendor.d.ts"
],
"include": [
"/**/*.ts"
],
"exclude": [
"node_modules"
]
}
================================================
FILE: dockerized-containers/e-Commerce-Cart/tslint.json
================================================
================================================
FILE: dockerized-containers/e-Commerce-Cart/uploads/documents/.gitkeep
================================================
================================================
FILE: dockerized-containers/e-Commerce-Cart/uploads/profile/.gitkeep
================================================
================================================
FILE: dockerized-containers/e-Commerce-Client/Dockerfile
================================================
FROM node:carbon
# Create app directory
WORKDIR /usr/src/app
# Bundle app source
COPY . .
# npm install
RUN npm install
# Run npm install --global grpc --unsafe-perm
EXPOSE 3003
CMD [ "npm", "run", "start" ]
================================================
FILE: dockerized-containers/e-Commerce-Client/README.md
================================================
## Simple ecommerce cart application
## Basic Overview -
This simple shopping cart prototype shows how React components and Redux can be used to build a
friendly user experience with instant visual updates and scaleable code in ecommerce applications.
#### Features
- Add and remove products from the floating cart
- Sort products by highest to lowest and lowest to highest price
- Filter products by available sizes
- Products persist in floating cart even after page reloads
- Responsive design for desktop, tablets and mobile
- Product stoppers for free shipping
- Unit tests, integration tests and e2e testing
#### Using
- React
- Redux - state management
- Nodejs
- Express CORS Middleware (Node and React run in different port)
- Nodemon - for a better development experience
- Concurrently - To run multiple tasks at once
- Axios - for promise HTTP requests
- CSS
- BEM methodology
- SASS
- Moxios - to stub http request
- Enzyme - to mount, shallow, render and query the DOM tree of React components
- Webdriverio - to do automated tests in a real browser environment
- Native local storage - to persist products in cart even after page reload
#### Requirements
- Node.js
- NPM
```javascript
/* First, Install the needed packages */
npm install
/* Then start both Node and React */
npm start
/* To run the tests */
npm run test
/* Running e2e tests */
npm run wdio
```
## About tests
- Unit tests
- All components have at least a basic smoke test
- Integration tests
- Fetch product and add to cart properly
- e2e
- Webdriverio - Add and remove product from cart
================================================
FILE: dockerized-containers/e-Commerce-Client/env.sh
================================================
# this environment vairables needs to be set in .env file in applciaiton root directory
# copy this file as .env and add the appropriate values as per environment.
# node & mysql
export NODE_ENV="local"
export PORT="3003"
================================================
FILE: dockerized-containers/e-Commerce-Client/firebase.json
================================================
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
================================================
FILE: dockerized-containers/e-Commerce-Client/package.json
================================================
{
"name": "app",
"version": "0.1.0",
"private": true,
"dependencies": {
"antd": "^3.13.2",
"axios": "^0.18.0",
"concurrently": "^4.0.1",
"cors": "^2.8.5",
"express": "^4.16.4",
"immutable": "^4.0.0-rc.12",
"moxios": "^0.4.0",
"react": "^16.6.1",
"react-dom": "^16.6.1",
"react-redux": "^5.1.1",
"react-router": "^3.2.0",
"react-router-dom": "^4.3.1",
"react-scripts": "^2.1.3",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0"
},
"scripts": {
"start": ". ./env.sh && react-scripts start",
"wdio": "wdio",
"build": "react-scripts build",
"test": "react-scripts test",
"test:coverage": "npm run test -- --coverage",
"format": "prettier --write \"**/*.+(js|json|css)\"",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx}",
"!/node_modules/",
"!src/index.js",
"!src/Root.js"
]
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"chai": "^4.2.0",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.7.0",
"enzyme-to-json": "^3.3.4",
"fetch-mock": "^7.2.5",
"firebase-tools": "^6.2.2",
"node-sass": "^4.10.0",
"nodemon": "^1.18.6",
"prop-types": "^15.6.2",
"react-test-renderer": "^16.6.3",
"redux-mock-store": "^1.5.3",
"sinon": "^7.1.1",
"wdio-mocha-framework": "^0.6.4",
"wdio-selenium-standalone-service": "0.0.12",
"wdio-spec-reporter": "^0.1.5",
"webdriverio": "^4.14.1"
}
}
================================================
FILE: dockerized-containers/e-Commerce-Client/public/index.html
================================================
{product.title}
{`${product.availableSizes[0]} | ${product.style}`}
Quantity: {product.quantity}
{`${product.currencyFormat} ${formatPrice(product.price)}`}
Add some products in the cart
:)
{`${cartTotal.currencyFormat} ${formatPrice( cartTotal.totalPrice, cartTotal.currencyId )}`}
{!!cartTotal.installments && ( {`OR UP TO ${cartTotal.installments} x ${ cartTotal.currencyFormat } ${formatPrice( cartTotal.totalPrice / cartTotal.installments, cartTotal.currencyId )}`} )}{product.title}
Sign in to find best rental scooty
{props.login.get('error') &&Are you new here? Create a New Account. Click here
forgot password Click here
{uiLinks}please be patient.
Sign in to find best rental scooty
Are you new here? Create a New Account. Click here
Are you new here? Create a New Account. Click here
);
const ui_no_access_token = (
|
|
Local News Application - A new article has been added to the website
|
|
Local News Application - A new article has been added to the website
|
A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.
## Description [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. ## Installation ```bash $ npm install ``` ## Running the app ```bash # development $ npm run start # watch mode $ npm run start:dev # production mode $ npm run start:prod ``` ## Test ```bash # unit tests $ npm run test # e2e tests $ npm run test:e2e # test coverage $ npm run test:cov ``` ## Support Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). ## Stay in touch - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) - Website - [https://nestjs.com](https://nestjs.com/) - Twitter - [@nestframework](https://twitter.com/nestframework) ## License Nest is [MIT licensed](LICENSE). ================================================ FILE: node-microservice-starter/users/nest-cli.json ================================================ { "collection": "@nestjs/schematics", "sourceRoot": "src" } ================================================ FILE: node-microservice-starter/users/package.json ================================================ { "name": "users", "version": "0.0.1", "description": "", "author": "", "private": true, "license": "UNLICENSED", "scripts": { "prebuild": "rimraf dist", "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { "@nestjs/common": "^7.0.0", "@nestjs/core": "^7.0.0", "@nestjs/platform-express": "^7.0.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^6.5.4" }, "devDependencies": { "@nestjs/cli": "^7.0.0", "@nestjs/schematics": "^7.0.0", "@nestjs/testing": "^7.0.0", "@types/express": "^4.17.3", "@types/jest": "26.0.10", "@types/node": "^13.9.1", "@types/supertest": "^2.0.8", "@typescript-eslint/eslint-plugin": "3.9.1", "@typescript-eslint/parser": "3.9.1", "eslint": "7.7.0", "eslint-config-prettier": "^6.10.0", "eslint-plugin-import": "^2.20.1", "jest": "26.4.2", "prettier": "^1.19.1", "supertest": "^4.0.2", "ts-jest": "26.2.0", "ts-loader": "^6.2.1", "ts-node": "9.0.0", "tsconfig-paths": "^3.9.0", "typescript": "^3.7.4" }, "jest": { "moduleFileExtensions": [ "js", "json", "ts" ], "rootDir": "src", "testRegex": ".spec.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" }, "coverageDirectory": "../coverage", "testEnvironment": "node" } } ================================================ FILE: node-microservice-starter/users/src/app.controller.spec.ts ================================================ import { Test, TestingModule } from '@nestjs/testing'; import { AppController } from './app.controller'; import { AppService } from './app.service'; describe('AppController', () => { let appController: AppController; beforeEach(async () => { const app: TestingModule = await Test.createTestingModule({ controllers: [AppController], providers: [AppService], }).compile(); appController = app.get
A Node.js CQRS/ES Swagger API Microservice Boilerplate
## Description This is an application boilerplate that demonstrates how to use Nest.js and Event Store to create a RESTful Users API microservice. Please note that commands have been implemented and they do write into the Event Store, however, queries for denormalized views have some boilerplate but it is up to you to implement them using your favorite database technology of choice. In case you don't feel like downloading dependencies locally, I've added support for Docker so follow those instructions in "Running the app" and you'll have everything up and running in less than 2 minutes. ## Dependency Table | Name | Version | | ------------- |:-------------: | | [EventStore](https://eventstore.org) | latest | | [Node.js](https://nodejs.org) | Dubnium | | [TypeScript](https://www.typescriptlang.org) | 3 | | [Docker Compose](https://docker.com) | 3 | ## Installation ```bash $ yarn ``` ## Running the app ```bash # development $ yarn start # watch mode $ yarn start:dev # production mode $ yarn start:prod # analyze production mode $ yarn start:analyze # using with Docker $ ./scripts/up.sh # to start $ ./scripts/down.sh # to stop ``` ## Relateds Links Medium Article (Part 1): https://medium.com/@qasimsoomro/building-microservices-using-node-js-with-ddd-cqrs-and-event-sourcing-part-1-of-2-52e0dc3d81df Medium Article (Part 2): https://medium.com/@qasimsoomro/building-microservices-using-node-js-with-ddd-cqrs-and-event-sourcing-part-2-of-2-9a5f6708e0f Swagger Explorer URL: http://localhost:7070/api Event Store URL: http://localhost:2113 ## Test ```bash # unit tests $ yarn test # e2e tests $ yarn test:e2e # test coverage $ yarn test:cov ``` ## Release History * 0.1.0 * The first proper release * CHANGE: Minimalist users app using Event Store * 0.0.1 * Work in progress ================================================ FILE: nodejs-cqrs-pattern/config.ts ================================================ import dotenv from 'dotenv'; import pkg from './package.json'; // Load environment variables from .env file dotenv.config(); const envDevelopmentName = 'development'; const env = process.env.NODE_ENV || envDevelopmentName; const configs = { base: { ENV: env, DEV: env === envDevelopmentName, // General NAME: process.env.APP_NAME || pkg.name, TITLE: process.env.APP_TITLE || 'Users', DESCRIPTION: process.env.APP_DESCRIPTION || 'Users API Microservice', // API PREFIX: process.env.APP_PREFIX || 'v1', VERSION: process.env.APP_VERSION || '1.0', API_EXPLORER_PATH: process.env.APP_API_EXPLORER_PATH || '/api', // Server HOST: process.env.APP_HOST || '0.0.0.0', PORT: process.env.APP_PORT || 7070, // Event Store EVENT_STORE_SETTINGS: { protocol: process.env.EVENT_STORE_PROTOCOL || 'http', hostname: process.env.EVENT_STORE_HOSTNAME || '0.0.0.0', tcpPort: process.env.EVENT_STORE_TCP_PORT || 1113, httpPort: process.env.EVENT_STORE_HTTP_PORT || 2113, credentials: { username: process.env.EVENT_STORE_CREDENTIALS_USERNAME || 'admin', password: process.env.EVENT_STORE_CREDENTIALS_PASSWORD || 'changeit', }, poolOptions: { min: process.env.EVENT_STORE_POOLOPTIONS_MIN || 1, max: process.env.EVENT_STORE_POOLOPTIONS_MAX || 10, }, }, }, development: {}, production: { PORT: process.env.APP_PORT || 7071, }, test: { PORT: 7072, }, }; const config = {...configs.base, ...configs[env]}; export {config}; ================================================ FILE: nodejs-cqrs-pattern/docker-compose.yml ================================================ # Documentation # https://docs.docker.com/compose/compose-file version: '3' services: eventstore: image: eventstore/eventstore ports: - 2113:2113 - 1113:1113 environment: - EVENTSTORE_RUN_PROJECTIONS=All - EVENTSTORE_START_STANDARD_PROJECTIONS=true networks: - backend boilerplate-nodejs-cqrs-es-swagger: build: context: "." command: ${CONTAINER_COMMAND} restart: always deploy: mode: replicated replicas: ${CONTAINER_SCALE} depends_on: - eventstore env_file: - "./.env" environment: - EVENT_STORE_HOSTNAME=eventstore ports: - "${CONTAINER_PORT}:7070" volumes: - "./src:/app/src" links: - eventstore networks: - backend networks: backend: driver: bridge ================================================ FILE: nodejs-cqrs-pattern/docs/README.md ================================================ # `/docs` Design and user documents. ================================================ FILE: nodejs-cqrs-pattern/githooks/README.md ================================================ # `/githooks` Git hooks. ================================================ FILE: nodejs-cqrs-pattern/nest-cli.json ================================================ { "language": "ts", "collection": "@nestjs/schematics", "sourceRoot": "src" } ================================================ FILE: nodejs-cqrs-pattern/nodemon-debug.json ================================================ { "watch": ["src"], "ext": "ts", "ignore": ["src/**/*.spec.ts"], "exec": "node --inspect-brk -r ts-node/register src/main.ts" } ================================================ FILE: nodejs-cqrs-pattern/nodemon.json ================================================ { "watch": ["src"], "ext": "ts", "ignore": ["src/**/*.spec.ts"], "exec": "ts-node -r tsconfig-paths/register src/main.ts", "events": { "restart": "osascript -e 'display notification \"boilerplate-nodejs-cqrs-es-swagger restarted\" with title \"nodemon\"'" } } ================================================ FILE: nodejs-cqrs-pattern/package.json ================================================ { "name": "boilerplate-nodejs-cqrs-es-swagger", "version": "0.0.0", "description": "description", "author": { "name": "Qasim Soomro", "email": "qasim@soomro.com", "url": "http://www.qasimsoomro.com" }, "license": "MIT", "scripts": { "build": "rm -rf dist && tsc", "build:docker": "docker build --force-rm -t boilerplate-nodejs-cqrs-es-swagger .", "start": "ts-node -r tsconfig-paths/register src/main.ts", "start:dev": "nodemon", "start:debug": "nodemon --config nodemon-debug.json", "prestart:prod": "npm run build --scripts-prepend-node-path", "start:prod": "node dist/src/main.js", "start:prod:analyze": "npm run prestart:prod && 0x dist/src/main.js", "lint": "tslint -p tsconfig.json -c tslint.json", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { "@nestjs/common": "^5.1.0", "@nestjs/core": "^5.1.0", "@nestjs/cqrs": "^5.1.1", "@nestjs/microservices": "^5.7.3", "@nestjs/swagger": "^2.5.1", "class-transformer": "^0.2.0", "class-validator": "^0.9.1", "cli-color": "^1.4.0", "dotenv": "^6.0.0", "fastify": "^1.13.0", "fastify-cors": "^0.2.0", "fastify-formbody": "^2.0.1", "fastify-swagger": "^0.15.1", "geteventstore-promise": "^3.1.1", "logform": "^2.1.2", "reflect-metadata": "^0.1.12", "rxjs": "^6.2.2", "rxjs-compat": "^6.4.0", "strict-event-emitter-types": "^2.0.0", "typescript": "^3.0.1", "winston": "^3.2.1", "xml2js": "^0.4.19" }, "devDependencies": { "0x": "^4.7.3", "@nestjs/testing": "^5.1.0", "@types/express": "^4.16.0", "@types/jest": "^23.3.9", "@types/node": "^10.7.1", "@types/supertest": "^2.0.5", "jest": "^23.5.0", "nodemon": "^1.18.3", "prettier": "^1.14.2", "rimraf": "^2.6.2", "supertest": "^3.1.0", "ts-jest": "^23.1.3", "ts-loader": "^4.4.2", "ts-node": "^7.0.1", "tsconfig-paths": "^3.5.0", "tslint": "5.11.0" }, "jest": { "moduleFileExtensions": [ "js", "json", "ts" ], "rootDir": "src", "testRegex": ".spec.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" }, "coverageDirectory": "../coverage", "testEnvironment": "node" } } ================================================ FILE: nodejs-cqrs-pattern/scripts/down.sh ================================================ #!/bin/sh export DIR_DATA_PATH="$PWD" export CONTAINER_COMMAND="yarn start:dev" export CONTAINER_SCALE="1" export CONTAINER_PORT="7070" docker-compose down ================================================ FILE: nodejs-cqrs-pattern/scripts/up.sh ================================================ #!/bin/sh export DIR_DATA_PATH="$PWD" export CONTAINER_COMMAND="yarn start:dev" export CONTAINER_SCALE="1" export CONTAINER_PORT="7070" docker-compose up --build ================================================ FILE: nodejs-cqrs-pattern/src/app.module.ts ================================================ import { Module, OnModuleInit } from '@nestjs/common'; import { UsersModule } from './users/users.module'; import { EventStoreModule } from './core/event-store/event-store.module'; @Module({ imports: [ EventStoreModule.forRoot(), /** ------------- */ UsersModule, ], }) export class AppModule implements OnModuleInit { async onModuleInit() {} } ================================================ FILE: nodejs-cqrs-pattern/src/core/event-store/event-store.class.ts ================================================ import { TCPClient, EventFactory} from 'geteventstore-promise'; /** * @class EventStore * @description EventStore.org */ export class EventStore { [x: string]: any; /** * @constructor */ constructor() { this.type = 'event-store'; this.eventFactory = new EventFactory(); } connect(config) { this.client = new TCPClient(config); return this; } getClient() { return this.client; } newEvent(name, payload) { return this.eventFactory.newEvent(name, payload); } close() { this.client.close(); return this; } } ================================================ FILE: nodejs-cqrs-pattern/src/core/event-store/event-store.interface.ts ================================================ export interface EventStoreMessage { streamId: string; eventId: string; eventNumber: number; eventType: string; created: Date; metadata: object; isJson: boolean; data: object; } ================================================ FILE: nodejs-cqrs-pattern/src/core/event-store/event-store.module.ts ================================================ import { Global, Module, DynamicModule } from '@nestjs/common'; import { EventStore } from './event-store'; import { eventStoreProviders } from './event-store.provider'; @Global() @Module({ providers: [ ...eventStoreProviders, { provide: 'EVENT_STORE_CONFIG', useValue: 'EVENT_STORE_CONFIG_USE_ENV', }, ], exports: [ ...eventStoreProviders, { provide: 'EVENT_STORE_CONFIG', useValue: 'EVENT_STORE_CONFIG_USE_ENV', }, ], }) export class EventStoreModule { static forRoot(): DynamicModule { return { module: EventStoreModule, }; } static forFeature(): DynamicModule { return { module: EventStoreModule, providers: [ EventStore, ], exports: [ EventStore, ], }; } } ================================================ FILE: nodejs-cqrs-pattern/src/core/event-store/event-store.provider.ts ================================================ import {config} from '../../../config'; import {EventStore} from './event-store.class'; export const eventStoreProviders = [ { provide: 'EVENT_STORE_PROVIDER', useFactory: ( eventStoreConfig?: any, ): any => { if (eventStoreConfig === 'EVENT_STORE_CONFIG_USE_ENV') { return new EventStore(); } }, inject: ['EVENT_STORE_CONFIG'], }, ]; ================================================ FILE: nodejs-cqrs-pattern/src/core/event-store/event-store.ts ================================================ import { Injectable, Inject, OnModuleDestroy, OnModuleInit } from '@nestjs/common'; import { IEventPublisher } from '@nestjs/cqrs/dist/interfaces/events/event-publisher.interface'; import { IMessageSource } from '@nestjs/cqrs/dist/interfaces/events/message-source.interface'; import { IEvent } from '@nestjs/cqrs/dist/interfaces/events/event.interface'; import { Subject, fromEvent } from 'rxjs'; import * as xml2js from 'xml2js'; import * as http from 'http'; import { config } from '../../../config'; const eventStoreHostUrl = config.EVENT_STORE_SETTINGS.protocol + `://${config.EVENT_STORE_SETTINGS.hostname}:${config.EVENT_STORE_SETTINGS.httpPort}/streams/`; /** * @class EventStore * @description The EventStore.org bridge. By design, the domain category * (i.e. user) events are being subscribed to. Upon events being received, * internal event handlers are responsible for the handling of events. */ @Injectable() export class EventStore implements IEventPublisher, IMessageSource { private eventStore: any; private eventHandlers: object; private category: string; constructor(@Inject('EVENT_STORE_PROVIDER') eventStore: any) { this.category = 'users'; this.eventStore = eventStore; this.eventStore.connect({ hostname: config.EVENT_STORE_SETTINGS.hostname, port: config.EVENT_STORE_SETTINGS.tcpPort, credentials: config.EVENT_STORE_SETTINGS.credentials, poolOptions: config.EVENT_STORE_SETTINGS.poolOptions, }); } async publish