├── .babelrc ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .lintstagedrc ├── .prettierrc.js ├── Capacity.md ├── LICENSE ├── README.md ├── _config.yml ├── api ├── index.js ├── util │ ├── file.js │ ├── index.js │ └── upload.js └── v1 │ ├── index.js │ └── info.txt ├── assets └── info.txt ├── collections └── user.js ├── config ├── default.json ├── info.txt └── staging.json ├── controllers ├── user.js └── util.js ├── db.js ├── dist ├── api │ ├── index.js │ ├── util │ │ ├── file.js │ │ ├── index.js │ │ └── upload.js │ └── v1 │ │ └── index.js ├── collections │ └── user.js ├── controllers │ ├── user.js │ └── util.js ├── db.js ├── main.js ├── plugins │ ├── auth.js │ ├── graphql.js │ ├── index.js │ ├── main.js │ └── rest.js ├── schema │ ├── gql │ │ ├── book.js │ │ ├── date.js │ │ ├── hello.js │ │ ├── indiecore.js │ │ ├── json.js │ │ └── user.js │ └── index.js ├── server.js ├── services │ └── user.js └── utilities │ ├── global.js │ ├── logger.js │ ├── mail.js │ ├── messages.js │ ├── rest.js │ ├── subscriptions.js │ ├── twilio.js │ └── universal.js ├── emailTemplates └── verifyEmail.html ├── main.html ├── main.js ├── package-lock.json ├── package.json ├── plugins ├── auth.js ├── graphql.js ├── index.js ├── main.js └── rest.js ├── private └── info.txt ├── schema ├── gql │ ├── book.js │ ├── date.js │ ├── hello.js │ ├── indiecore.js │ ├── json.js │ └── user.js └── index.js ├── server.js ├── services └── user.js ├── updated_modules └── good-master.zip └── utilities ├── global.js ├── logger.js ├── mail.js ├── messages.js ├── rest.js ├── subscriptions.js ├── twilio.js └── universal.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env"], 3 | "plugins": ["transform-object-rest-spread"] 4 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # /node_modules/* and /bower_components/* ignored by default 2 | 3 | # Ignore build directory 4 | dist/* -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | commonjs: true, 5 | es6: true 6 | }, 7 | extends: ['standard', 'eslint:recommended', 'prettier'], 8 | plugins: ['prettier'], 9 | parserOptions: { 10 | sourceType: 'module' 11 | }, 12 | rules: { 13 | indent: [2, 2], 14 | 'linebreak-style': [2, 'unix'], 15 | quotes: [1, 'single'], 16 | semi: [2, 'always'], 17 | 'prettier/prettier': [2, null, '@prettier'] 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # assets directory 61 | assets 62 | 63 | # build directory 64 | # dist -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "**/*.js": [ 3 | "npm run lint", 4 | "git add" 5 | ] 6 | } -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | singleQuote: true, 4 | trailingComma: 'none' 5 | }; 6 | -------------------------------------------------------------------------------- /Capacity.md: -------------------------------------------------------------------------------- 1 | Capacity Planning 2 | ------------------- 3 | Hours 4 | ------------------- 5 | Dev - 6 6 | UI-Dev - 6 7 | QA - 6 8 | ------------------- 9 | Total Hours - 18 10 | ------------------- 11 | Days - 15 12 | ------------------- 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Lancy Goyal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hano 2 | 3 | GraphQL, Hapi and Node Project For Scaleable Apps. 4 | 5 | ### Includes 6 | 7 | - Node 8 | - Hapi v17 9 | - Apollo GraphQL 10 | - Subscriptions 11 | - GraphiQL 12 | - Prettier 13 | - Husky 14 | - ES-Next 15 | - ESLint 16 | 17 | ### Running it 18 | 19 | ``` 20 | npm install 21 | npm start 22 | ``` 23 | 24 | ### Folder structure 25 | 26 | . 27 | ├── api # Rest api's folder 28 | │ ├── v1 29 | │ | └── util # Routes 30 | │ | └── index.js 31 | ├── config # Config Folder 32 | ├── controllers # Controllers Folder For Api's 33 | ├── collections # Collections Folder 34 | ├── plugins # Plugins Folder 35 | ├── schema # Schema Setup 36 | │ ├── gql # GraphQL Folder 37 | │ | └── index.js 38 | ├── services # Services Folder For Api's 39 | ├── utilities # Utility Folder 40 | ├── main.js # Main server file initiating hapi server 41 | └── package.json # Node dependencies 42 | 43 | ### Learn more 44 | 45 | - [Hapi](https://hapijs.com) 46 | - [Hapi Api Docs](https://github.com/hapijs/hapi/blob/master/API.md) 47 | - [GraphQL](http://graphql.org/) 48 | - [Apollo Docs](https://www.apollographql.com/docs/apollo-server/) 49 | - [Apollo Hapi Docs](https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-hapi) 50 | - [Mongoose Guide](http://mongoosejs.com/docs/guide.html) 51 | - [Es6 Cheatsheet](https://github.com/DrkSephy/es6-cheatsheet/blob/master/README.md) 52 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /api/index.js: -------------------------------------------------------------------------------- 1 | import v1 from './v1'; 2 | import util from './util'; 3 | 4 | export default [...v1, ...util]; 5 | -------------------------------------------------------------------------------- /api/util/file.js: -------------------------------------------------------------------------------- 1 | import { downloadFile } from '../../controllers/util'; 2 | 3 | export default { 4 | method: 'GET', 5 | path: '/api/util/file/{fileName}', 6 | config: { 7 | auth: false, 8 | description: 'Api service used to download file.', 9 | tags: ['api', 'util'] 10 | }, 11 | handler: downloadFile 12 | }; 13 | -------------------------------------------------------------------------------- /api/util/index.js: -------------------------------------------------------------------------------- 1 | import file from './file'; 2 | import upload from './upload'; 3 | 4 | export default [file, upload]; 5 | -------------------------------------------------------------------------------- /api/util/upload.js: -------------------------------------------------------------------------------- 1 | import { uploadFile } from '../../controllers/util'; 2 | 3 | export default { 4 | method: 'POST', 5 | path: '/api/util/upload', 6 | config: { 7 | auth: false, 8 | description: 'Api service used to upload file.', 9 | tags: ['api', 'util'], 10 | payload: { 11 | output: 'stream', 12 | allow: 'multipart/form-data', 13 | maxBytes: 1e7 14 | } 15 | }, 16 | handler: uploadFile 17 | }; 18 | -------------------------------------------------------------------------------- /api/v1/index.js: -------------------------------------------------------------------------------- 1 | export default []; 2 | -------------------------------------------------------------------------------- /api/v1/info.txt: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | 3 | * In this folder we have our v1 api routes. 4 | 5 | ---------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /assets/info.txt: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | 3 | * In this folder we are storing Images etc. 4 | 5 | ---------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /collections/user.js: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | * @ description : This file defines the user schema for mongodb. 3 | ----------------------------------------------------------------------- */ 4 | 5 | import Mongoose from 'mongoose'; 6 | import { getTimeStamp } from '../utilities/universal'; 7 | 8 | const Schema = Mongoose.Schema; 9 | 10 | class UserClass { 11 | static checkEmail(email) { 12 | return this.findOne({ email }); 13 | } 14 | static checkToken(token) { 15 | return this.findOne({ 'loginToken.token': token }); 16 | } 17 | static register(payload) { 18 | return this(payload).save(); 19 | } 20 | static login(email, password) { 21 | return this.findOne({ 22 | email, 23 | password 24 | }); 25 | } 26 | static onLoginDone(userId, payload, loginToken) { 27 | let updateData = { 28 | $push: { loginToken: { token: loginToken } }, 29 | $set: { 30 | lastLogin: getTimeStamp(), 31 | updatedAt: getTimeStamp() 32 | } 33 | }; 34 | 35 | return this.findByIdAndUpdate(userId, updateData, { new: true }); 36 | } 37 | static logout(userId, token) { 38 | let updateData = { 39 | $set: { 40 | 'device.token': '', 41 | updatedAt: getTimeStamp() 42 | }, 43 | $pull: { loginToken: { token } } 44 | }; 45 | return this.findByIdAndUpdate(userId, updateData); 46 | } 47 | } 48 | 49 | const UserSchema = new Schema({ 50 | fullName: { type: String, required: true }, 51 | email: { type: String, required: true }, 52 | password: { type: String, required: true }, 53 | role: { type: String, required: true, default: 'user' }, // business, user, admin 54 | verified: { 55 | token: { type: String, default: '' }, 56 | status: { type: Boolean, default: false } 57 | }, 58 | loginToken: [ 59 | { 60 | token: { type: String, default: '' }, 61 | when: { type: Number, default: getTimeStamp } 62 | } 63 | ], 64 | lastLogin: { type: Number }, 65 | isActive: { type: Boolean, default: true }, 66 | createdAt: { type: Number, default: getTimeStamp }, 67 | updatedAt: { type: Number, default: getTimeStamp } 68 | }); 69 | 70 | UserSchema.loadClass(UserClass); 71 | 72 | export default Mongoose.model('User', UserSchema); 73 | -------------------------------------------------------------------------------- /config/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "hano", 4 | "host": "127.0.0.1", 5 | "port": 3005, 6 | "socket": 3007, 7 | "debug": true, 8 | "logLevel": "debug", 9 | "jwtAlgo": "HS512", 10 | "jwtKey": "hano" 11 | }, 12 | "db": { 13 | "name": "hano", 14 | "host": "127.0.0.1", 15 | "auth": false, 16 | "username": "", 17 | "password": "", 18 | "port": 27017, 19 | "mongoose": { 20 | "useMongoClient": true, 21 | "autoIndex": true, // Don't build indexes 22 | "poolSize": 10, // Maintain up to 10 socket connections 23 | // If not connected, return errors immediately rather than waiting for reconnect 24 | "bufferMaxEntries": 0 25 | } 26 | }, 27 | "ios": { 28 | "cert": "", 29 | "key": "", 30 | "gateway": "gateway.sandbox.push.apple.com", 31 | "production": true 32 | }, 33 | "android": { 34 | "senderId": "", 35 | "apiKey": "" 36 | }, 37 | "twillio": { 38 | "sid": "", 39 | "token": "", 40 | "number": "" 41 | }, 42 | "smtp": { 43 | "smtpUser": "", 44 | "smtpPass": "", 45 | "smtpPort": 587, //25, 46 | "smtpServer": "smtp.gmail.com", 47 | "mailFrom": "Hano " 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /config/info.txt: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | 3 | * config of your app. 4 | 5 | ---------------------------------------------------------------------*/ 6 | 7 | Example exporting to the O/S before loading your app. 8 | 9 | cd /my/application 10 | export NODE_ENV=staging 11 | node myapp.js 12 | Example passing on the command line: 13 | 14 | cd /my/application 15 | NODE_ENV=stage node myapp.js 16 | Example setting in JavaScript before the first load of node-config: 17 | 18 | process.env.NODE_ENV = "staging"; 19 | var config = require('config'); 20 | -------------------------------------------------------------------------------- /config/staging.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "hano", 4 | "host": "127.0.0.1", 5 | "port": 3005, 6 | "socket": 3007, 7 | "debug": true, 8 | "logLevel": "info", 9 | "jwtAlgo": "HS512", 10 | "jwtKey": "hano" 11 | }, 12 | "db": { 13 | "name": "hano", 14 | "host": "127.0.0.1", 15 | "auth": false, 16 | "username": "", 17 | "password": "", 18 | "port": 27017, 19 | "mongoose": { 20 | "useMongoClient": true, 21 | "autoIndex": true, // Don't build indexes 22 | "poolSize": 10, // Maintain up to 10 socket connections 23 | // If not connected, return errors immediately rather than waiting for reconnect 24 | "bufferMaxEntries": 0 25 | } 26 | }, 27 | "ios": { 28 | "cert": "", 29 | "key": "", 30 | "gateway": "gateway.sandbox.push.apple.com", 31 | "production": true 32 | }, 33 | "android": { 34 | "sender_id": "", 35 | "api_key": "" 36 | }, 37 | "twillio": { 38 | "sid": "", 39 | "token": "", 40 | "number": "" 41 | }, 42 | "smtp": { 43 | "smtpUser": "", 44 | "smtpPass": "", 45 | "smtpPort": 587, // 25, 46 | "smtpServer": "", 47 | "mailFrom": "Hano " 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /controllers/user.js: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | * @ description : This is the user controller layer. 3 | ----------------------------------------------------------------------- */ 4 | 5 | import { register, login, logout } from '../services/user'; 6 | import { failAction } from '../utilities/rest'; 7 | import Messages from '../utilities/messages'; 8 | // import logger from '../utilities/logger'; 9 | 10 | export const registerUser = async (root, payload, context) => { 11 | try { 12 | return await register(payload); 13 | } catch (error) { 14 | failAction(error.message); 15 | } 16 | }; 17 | 18 | export const loginUser = async (root, payload, context) => { 19 | try { 20 | return await login(payload); 21 | } catch (error) { 22 | failAction(error.message); 23 | } 24 | }; 25 | 26 | export const logoutUser = async (root, payload, context) => { 27 | const { auth: { isAuthenticated, message } } = context; 28 | try { 29 | if (!isAuthenticated) throw new Error(message); 30 | const { auth: { credentials: { user, token } } } = context; 31 | await logout({ user, token }); 32 | return Messages.logoutSuccessfull; 33 | } catch (error) { 34 | failAction(error.message); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /controllers/util.js: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | * @ description : This is the util controller layer. 3 | ----------------------------------------------------------------------- */ 4 | 5 | import { uploader, imageFilter } from '../utilities/universal'; 6 | import { failAction, successAction } from '../utilities/rest'; 7 | // import Messages from '../utilities/messages'; 8 | // import logger from '../utilities/logger'; 9 | 10 | const UPLOAD_PATH = 'assets/'; 11 | const fileOptions = { dest: UPLOAD_PATH, fileFilter: imageFilter }; 12 | 13 | export const downloadFile = { 14 | directory: { 15 | path: UPLOAD_PATH, 16 | redirectToSlash: false, 17 | index: false 18 | } 19 | }; 20 | 21 | export const uploadFile = async (request, h) => { 22 | const { payload } = request; 23 | const file = payload['file']; 24 | try { 25 | const data = await uploader(file, fileOptions); 26 | return successAction(data); 27 | } catch (error) { 28 | failAction(error.message); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /db.js: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------------- 2 | * @ description : This is the db configration file. 3 | ---------------------------------------------------------------------------------- */ 4 | 5 | import Mongoose from 'mongoose'; 6 | import Bluebird from 'bluebird'; 7 | import config from 'config'; 8 | import logger from './utilities/logger'; 9 | 10 | // Connect to MongoDB 11 | const db = config.get('db'); 12 | 13 | export default async () => { 14 | // Build the connection string. 15 | 16 | const mongoUrl = db.auth 17 | ? `mongodb://${db.username}:${db.password}@${db.host}:${db.port}/${db.name}` 18 | : `mongodb://${db.host}:${db.port}/${db.name}`; 19 | 20 | Mongoose.Promise = Bluebird; 21 | 22 | Mongoose.connect(mongoUrl, config.get('db.mongoose'), err => { 23 | if (err) { 24 | logger.error('+++ DB Error', err); 25 | // process.exit(1); 26 | } else { 27 | logger.info('+++ MongoDB Connected'); 28 | } 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /dist/api/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _v = require('./v1'); 8 | 9 | var _v2 = _interopRequireDefault(_v); 10 | 11 | var _util = require('./util'); 12 | 13 | var _util2 = _interopRequireDefault(_util); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } 18 | 19 | exports.default = [].concat(_toConsumableArray(_v2.default), _toConsumableArray(_util2.default)); -------------------------------------------------------------------------------- /dist/api/util/file.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _util = require('../../controllers/util'); 8 | 9 | exports.default = { 10 | method: 'GET', 11 | path: '/api/util/file/{fileName}', 12 | config: { 13 | auth: false, 14 | description: 'Api service used to download file.', 15 | tags: ['api', 'util'] 16 | }, 17 | handler: _util.downloadFile 18 | }; -------------------------------------------------------------------------------- /dist/api/util/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _file = require('./file'); 8 | 9 | var _file2 = _interopRequireDefault(_file); 10 | 11 | var _upload = require('./upload'); 12 | 13 | var _upload2 = _interopRequireDefault(_upload); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | exports.default = [_file2.default, _upload2.default]; -------------------------------------------------------------------------------- /dist/api/util/upload.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _util = require('../../controllers/util'); 8 | 9 | exports.default = { 10 | method: 'POST', 11 | path: '/api/util/upload', 12 | config: { 13 | auth: false, 14 | description: 'Api service used to upload file.', 15 | tags: ['api', 'util'], 16 | payload: { 17 | output: 'stream', 18 | allow: 'multipart/form-data', 19 | maxBytes: 1e7 20 | } 21 | }, 22 | handler: _util.uploadFile 23 | }; -------------------------------------------------------------------------------- /dist/api/v1/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = []; -------------------------------------------------------------------------------- /dist/collections/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* ----------------------------------------------------------------------- 8 | * @ description : This file defines the user schema for mongodb. 9 | ----------------------------------------------------------------------- */ 10 | 11 | var _mongoose = require('mongoose'); 12 | 13 | var _mongoose2 = _interopRequireDefault(_mongoose); 14 | 15 | var _universal = require('../utilities/universal'); 16 | 17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 18 | 19 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 20 | 21 | var Schema = _mongoose2.default.Schema; 22 | 23 | var UserClass = function () { 24 | function UserClass() { 25 | _classCallCheck(this, UserClass); 26 | } 27 | 28 | _createClass(UserClass, null, [{ 29 | key: 'checkEmail', 30 | value: function checkEmail(email) { 31 | return this.findOne({ email: email }); 32 | } 33 | }, { 34 | key: 'checkToken', 35 | value: function checkToken(token) { 36 | return this.findOne({ 'loginToken.token': token }); 37 | } 38 | }, { 39 | key: 'register', 40 | value: function register(payload) { 41 | return this(payload).save(); 42 | } 43 | }, { 44 | key: 'login', 45 | value: function login(email, password) { 46 | return this.findOne({ 47 | email: email, 48 | password: password 49 | }); 50 | } 51 | }, { 52 | key: 'onLoginDone', 53 | value: function onLoginDone(userId, payload, loginToken) { 54 | var updateData = { 55 | $push: { loginToken: { token: loginToken } }, 56 | $set: { 57 | lastLogin: (0, _universal.getTimeStamp)(), 58 | updatedAt: (0, _universal.getTimeStamp)() 59 | } 60 | }; 61 | 62 | return this.findByIdAndUpdate(userId, updateData, { new: true }); 63 | } 64 | }, { 65 | key: 'logout', 66 | value: function logout(userId, token) { 67 | var updateData = { 68 | $set: { 69 | 'device.token': '', 70 | updatedAt: (0, _universal.getTimeStamp)() 71 | }, 72 | $pull: { loginToken: { token: token } } 73 | }; 74 | return this.findByIdAndUpdate(userId, updateData); 75 | } 76 | }]); 77 | 78 | return UserClass; 79 | }(); 80 | 81 | var UserSchema = new Schema({ 82 | fullName: { type: String, required: true }, 83 | email: { type: String, required: true }, 84 | password: { type: String, required: true }, 85 | role: { type: String, required: true, default: 'user' }, // business, user, admin 86 | verified: { 87 | token: { type: String, default: '' }, 88 | status: { type: Boolean, default: false } 89 | }, 90 | loginToken: [{ 91 | token: { type: String, default: '' }, 92 | when: { type: Number, default: _universal.getTimeStamp } 93 | }], 94 | lastLogin: { type: Number }, 95 | isActive: { type: Boolean, default: true }, 96 | createdAt: { type: Number, default: _universal.getTimeStamp }, 97 | updatedAt: { type: Number, default: _universal.getTimeStamp } 98 | }); 99 | 100 | UserSchema.loadClass(UserClass); 101 | 102 | exports.default = _mongoose2.default.model('User', UserSchema); -------------------------------------------------------------------------------- /dist/controllers/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.logoutUser = exports.loginUser = exports.registerUser = undefined; 7 | 8 | var _user = require('../services/user'); 9 | 10 | var _rest = require('../utilities/rest'); 11 | 12 | var _messages = require('../utilities/messages'); 13 | 14 | var _messages2 = _interopRequireDefault(_messages); 15 | 16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17 | 18 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* ----------------------------------------------------------------------- 19 | * @ description : This is the user controller layer. 20 | ----------------------------------------------------------------------- */ 21 | 22 | // import logger from '../utilities/logger'; 23 | 24 | var registerUser = exports.registerUser = function () { 25 | var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(root, payload, context) { 26 | return regeneratorRuntime.wrap(function _callee$(_context) { 27 | while (1) { 28 | switch (_context.prev = _context.next) { 29 | case 0: 30 | _context.prev = 0; 31 | _context.next = 3; 32 | return (0, _user.register)(payload); 33 | 34 | case 3: 35 | return _context.abrupt('return', _context.sent); 36 | 37 | case 6: 38 | _context.prev = 6; 39 | _context.t0 = _context['catch'](0); 40 | 41 | (0, _rest.failAction)(_context.t0.message); 42 | 43 | case 9: 44 | case 'end': 45 | return _context.stop(); 46 | } 47 | } 48 | }, _callee, undefined, [[0, 6]]); 49 | })); 50 | 51 | return function registerUser(_x, _x2, _x3) { 52 | return _ref.apply(this, arguments); 53 | }; 54 | }(); 55 | 56 | var loginUser = exports.loginUser = function () { 57 | var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(root, payload, context) { 58 | return regeneratorRuntime.wrap(function _callee2$(_context2) { 59 | while (1) { 60 | switch (_context2.prev = _context2.next) { 61 | case 0: 62 | _context2.prev = 0; 63 | _context2.next = 3; 64 | return (0, _user.login)(payload); 65 | 66 | case 3: 67 | return _context2.abrupt('return', _context2.sent); 68 | 69 | case 6: 70 | _context2.prev = 6; 71 | _context2.t0 = _context2['catch'](0); 72 | 73 | (0, _rest.failAction)(_context2.t0.message); 74 | 75 | case 9: 76 | case 'end': 77 | return _context2.stop(); 78 | } 79 | } 80 | }, _callee2, undefined, [[0, 6]]); 81 | })); 82 | 83 | return function loginUser(_x4, _x5, _x6) { 84 | return _ref2.apply(this, arguments); 85 | }; 86 | }(); 87 | 88 | var logoutUser = exports.logoutUser = function () { 89 | var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(root, payload, context) { 90 | var _context$auth, isAuthenticated, message, _context$auth$credent, user, token; 91 | 92 | return regeneratorRuntime.wrap(function _callee3$(_context3) { 93 | while (1) { 94 | switch (_context3.prev = _context3.next) { 95 | case 0: 96 | _context$auth = context.auth, isAuthenticated = _context$auth.isAuthenticated, message = _context$auth.message; 97 | _context3.prev = 1; 98 | 99 | if (isAuthenticated) { 100 | _context3.next = 4; 101 | break; 102 | } 103 | 104 | throw new Error(message); 105 | 106 | case 4: 107 | _context$auth$credent = context.auth.credentials, user = _context$auth$credent.user, token = _context$auth$credent.token; 108 | _context3.next = 7; 109 | return (0, _user.logout)({ user: user, token: token }); 110 | 111 | case 7: 112 | return _context3.abrupt('return', _messages2.default.logoutSuccessfull); 113 | 114 | case 10: 115 | _context3.prev = 10; 116 | _context3.t0 = _context3['catch'](1); 117 | 118 | (0, _rest.failAction)(_context3.t0.message); 119 | 120 | case 13: 121 | case 'end': 122 | return _context3.stop(); 123 | } 124 | } 125 | }, _callee3, undefined, [[1, 10]]); 126 | })); 127 | 128 | return function logoutUser(_x7, _x8, _x9) { 129 | return _ref3.apply(this, arguments); 130 | }; 131 | }(); -------------------------------------------------------------------------------- /dist/controllers/util.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.uploadFile = exports.downloadFile = undefined; 7 | 8 | var _universal = require('../utilities/universal'); 9 | 10 | var _rest = require('../utilities/rest'); 11 | 12 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* ----------------------------------------------------------------------- 13 | * @ description : This is the util controller layer. 14 | ----------------------------------------------------------------------- */ 15 | 16 | // import Messages from '../utilities/messages'; 17 | // import logger from '../utilities/logger'; 18 | 19 | var UPLOAD_PATH = 'assets/'; 20 | var fileOptions = { dest: UPLOAD_PATH, fileFilter: _universal.imageFilter }; 21 | 22 | var downloadFile = exports.downloadFile = { 23 | directory: { 24 | path: UPLOAD_PATH, 25 | redirectToSlash: false, 26 | index: false 27 | } 28 | }; 29 | 30 | var uploadFile = exports.uploadFile = function () { 31 | var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(request, h) { 32 | var payload, file, data; 33 | return regeneratorRuntime.wrap(function _callee$(_context) { 34 | while (1) { 35 | switch (_context.prev = _context.next) { 36 | case 0: 37 | payload = request.payload; 38 | file = payload['file']; 39 | _context.prev = 2; 40 | _context.next = 5; 41 | return (0, _universal.uploader)(file, fileOptions); 42 | 43 | case 5: 44 | data = _context.sent; 45 | return _context.abrupt('return', (0, _rest.successAction)(data)); 46 | 47 | case 9: 48 | _context.prev = 9; 49 | _context.t0 = _context['catch'](2); 50 | 51 | (0, _rest.failAction)(_context.t0.message); 52 | 53 | case 12: 54 | case 'end': 55 | return _context.stop(); 56 | } 57 | } 58 | }, _callee, undefined, [[2, 9]]); 59 | })); 60 | 61 | return function uploadFile(_x, _x2) { 62 | return _ref.apply(this, arguments); 63 | }; 64 | }(); -------------------------------------------------------------------------------- /dist/db.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _mongoose = require('mongoose'); 8 | 9 | var _mongoose2 = _interopRequireDefault(_mongoose); 10 | 11 | var _bluebird = require('bluebird'); 12 | 13 | var _bluebird2 = _interopRequireDefault(_bluebird); 14 | 15 | var _config = require('config'); 16 | 17 | var _config2 = _interopRequireDefault(_config); 18 | 19 | var _logger = require('./utilities/logger'); 20 | 21 | var _logger2 = _interopRequireDefault(_logger); 22 | 23 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 24 | 25 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* --------------------------------------------------------------------------------- 26 | * @ description : This is the db configration file. 27 | ---------------------------------------------------------------------------------- */ 28 | 29 | // Connect to MongoDB 30 | var db = _config2.default.get('db'); 31 | 32 | exports.default = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { 33 | var mongoUrl; 34 | return regeneratorRuntime.wrap(function _callee$(_context) { 35 | while (1) { 36 | switch (_context.prev = _context.next) { 37 | case 0: 38 | // Build the connection string. 39 | mongoUrl = 'mongodb://' + db.host + ':' + db.port + '/' + db.name; 40 | 41 | 42 | _mongoose2.default.Promise = _bluebird2.default; 43 | 44 | _mongoose2.default.connect(mongoUrl, _config2.default.get('db.mongoose'), function (err) { 45 | if (err) { 46 | _logger2.default.error('+++ DB Error', err); 47 | // process.exit(1); 48 | } else { 49 | _logger2.default.info('+++ MongoDB Connected'); 50 | } 51 | }); 52 | 53 | case 3: 54 | case 'end': 55 | return _context.stop(); 56 | } 57 | } 58 | }, _callee, undefined); 59 | })); -------------------------------------------------------------------------------- /dist/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('babel-polyfill'); 4 | 5 | require('babel-core/register'); 6 | 7 | var _db = require('./db'); 8 | 9 | var _db2 = _interopRequireDefault(_db); 10 | 11 | var _server = require('./server'); 12 | 13 | var _server2 = _interopRequireDefault(_server); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | // creating REST API server connection. 18 | /* --------------------------------------------------------------------------------- 19 | * @ description : This is the main startup server file to configure the application. 20 | ---------------------------------------------------------------------------------- */ 21 | 22 | (0, _server2.default)(); 23 | 24 | // create DB connection. 25 | (0, _db2.default)(); -------------------------------------------------------------------------------- /dist/plugins/auth.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _rest = require('../utilities/rest'); 8 | 9 | exports.default = { 10 | name: 'Auth', 11 | version: '1.0.0', 12 | register: function register(server, options) { 13 | var scheme = function scheme() { 14 | return { 15 | authenticate: _rest.authorization 16 | }; 17 | }; 18 | server.auth.scheme('jwt', scheme); 19 | server.auth.strategy('jwt', 'jwt'); 20 | } 21 | }; /* ------------------------------------------------------------------------------------------------ 22 | * @ description : Here we are creating the auth plugin. 23 | ------------------------------------------------------------------------------------------------- */ -------------------------------------------------------------------------------- /dist/plugins/graphql.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | var _apolloServerHapi = require('apollo-server-hapi'); 10 | 11 | var _apolloErrors = require('apollo-errors'); 12 | 13 | var _subscriptionsTransportWs = require('subscriptions-transport-ws'); 14 | 15 | var _graphql = require('graphql'); 16 | 17 | var _rest = require('../utilities/rest'); 18 | 19 | var _schema = require('../schema'); 20 | 21 | var _schema2 = _interopRequireDefault(_schema); 22 | 23 | var _logger = require('../utilities/logger'); 24 | 25 | var _logger2 = _interopRequireDefault(_logger); 26 | 27 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 28 | 29 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* ------------------------------------------------------------------------------------------------ 30 | * @ description : Here we are creating the Graphql Plugin. 31 | ------------------------------------------------------------------------------------------------- */ 32 | 33 | exports.default = { 34 | name: 'Graphql', 35 | version: '1.0.0', 36 | register: function () { 37 | var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(server, _ref) { 38 | var _ref$path = _ref.path, 39 | path = _ref$path === undefined ? '/graphql' : _ref$path, 40 | _ref$subscriptionsPat = _ref.subscriptionsPath, 41 | subscriptionsPath = _ref$subscriptionsPat === undefined ? '/subscriptions' : _ref$subscriptionsPat, 42 | _ref$graphiql = _ref.graphiql, 43 | graphiql = _ref$graphiql === undefined ? false : _ref$graphiql, 44 | _ref$graphiqlPath = _ref.graphiqlPath, 45 | graphiqlPath = _ref$graphiqlPath === undefined ? '/graphiql' : _ref$graphiqlPath, 46 | graphiqlOptions = _ref.graphiqlOptions; 47 | var subscriptionsEndpoint, plugins; 48 | return regeneratorRuntime.wrap(function _callee3$(_context3) { 49 | while (1) { 50 | switch (_context3.prev = _context3.next) { 51 | case 0: 52 | subscriptionsEndpoint = 'ws://' + server.info.host + ':' + server.info.port + subscriptionsPath; 53 | plugins = [{ 54 | plugin: _apolloServerHapi.graphqlHapi, 55 | options: { 56 | path: path, 57 | graphqlOptions: function () { 58 | var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(request) { 59 | return regeneratorRuntime.wrap(function _callee$(_context) { 60 | while (1) { 61 | switch (_context.prev = _context.next) { 62 | case 0: 63 | _context.next = 2; 64 | return (0, _rest.authContext)(request); 65 | 66 | case 2: 67 | _context.t0 = _context.sent; 68 | _context.t1 = { 69 | auth: _context.t0 70 | }; 71 | _context.t2 = _schema2.default; 72 | _context.t3 = _apolloErrors.formatError; 73 | return _context.abrupt('return', { 74 | context: _context.t1, 75 | schema: _context.t2, 76 | formatError: _context.t3 77 | }); 78 | 79 | case 7: 80 | case 'end': 81 | return _context.stop(); 82 | } 83 | } 84 | }, _callee, undefined); 85 | })); 86 | 87 | function graphqlOptions(_x3) { 88 | return _ref3.apply(this, arguments); 89 | } 90 | 91 | return graphqlOptions; 92 | }(), 93 | route: { 94 | cors: true 95 | } 96 | } 97 | }]; 98 | 99 | 100 | if (graphiql) plugins.push({ 101 | plugin: _apolloServerHapi.graphiqlHapi, 102 | options: { 103 | path: graphiqlPath, 104 | graphiqlOptions: _extends({ 105 | endpointURL: path 106 | }, graphiqlOptions, { 107 | subscriptionsEndpoint: subscriptionsEndpoint 108 | }) 109 | } 110 | }); 111 | 112 | // setup graphql server 113 | _context3.next = 5; 114 | return server.register(plugins); 115 | 116 | case 5: 117 | 118 | // setup subscription server 119 | _subscriptionsTransportWs.SubscriptionServer.create({ 120 | execute: _graphql.execute, 121 | subscribe: _graphql.subscribe, 122 | schema: _schema2.default, 123 | onConnect: function () { 124 | var _ref5 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(_ref4, webSocket) { 125 | var token = _ref4.token; 126 | return regeneratorRuntime.wrap(function _callee2$(_context2) { 127 | while (1) { 128 | switch (_context2.prev = _context2.next) { 129 | case 0: 130 | _logger2.default.info('+++ Subscription Connected'); 131 | 132 | // const userContext = authContext(token); 133 | 134 | // if (userContext.isAuthenticated) { 135 | // return { ...userContext }; 136 | // } 137 | 138 | // throw new Error(userContext.message); 139 | 140 | return _context2.abrupt('return'); 141 | 142 | case 2: 143 | case 'end': 144 | return _context2.stop(); 145 | } 146 | } 147 | }, _callee2, undefined); 148 | })); 149 | 150 | function onConnect(_x4, _x5) { 151 | return _ref5.apply(this, arguments); 152 | } 153 | 154 | return onConnect; 155 | }(), 156 | onDisconnect: function onDisconnect(webSocket) { 157 | _logger2.default.info('+++ Subscription Disconnected'); 158 | return; 159 | } 160 | }, { 161 | server: server.listener, 162 | path: subscriptionsPath 163 | }); 164 | 165 | _logger2.default.info('+++ GraphQL running at: ' + server.info.uri + path); 166 | _logger2.default.info('+++ GraphQL Subscriptions running at: ' + subscriptionsEndpoint); 167 | _logger2.default.info('+++ GraphiQL running at: ' + server.info.uri + graphiqlPath); 168 | 169 | case 9: 170 | case 'end': 171 | return _context3.stop(); 172 | } 173 | } 174 | }, _callee3, undefined); 175 | })); 176 | 177 | function register(_x, _x2) { 178 | return _ref2.apply(this, arguments); 179 | } 180 | 181 | return register; 182 | }() 183 | }; -------------------------------------------------------------------------------- /dist/plugins/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _inert = require('inert'); 8 | 9 | var _inert2 = _interopRequireDefault(_inert); 10 | 11 | var _vision = require('vision'); 12 | 13 | var _vision2 = _interopRequireDefault(_vision); 14 | 15 | var _good = require('good'); 16 | 17 | var _good2 = _interopRequireDefault(_good); 18 | 19 | var _config = require('config'); 20 | 21 | var _config2 = _interopRequireDefault(_config); 22 | 23 | var _auth = require('./auth'); 24 | 25 | var _auth2 = _interopRequireDefault(_auth); 26 | 27 | var _rest = require('./rest'); 28 | 29 | var _rest2 = _interopRequireDefault(_rest); 30 | 31 | var _main = require('./main'); 32 | 33 | var _main2 = _interopRequireDefault(_main); 34 | 35 | var _graphql = require('./graphql'); 36 | 37 | var _graphql2 = _interopRequireDefault(_graphql); 38 | 39 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 40 | 41 | // import Pack from '../package.json'; 42 | /* ---------------------------------------------------------------------- 43 | * @ description : Here config all hapi plugIns and custom plugIns. 44 | ----------------------------------------------------------------------- */ 45 | 46 | var app = _config2.default.get('app'); 47 | 48 | /** 49 | * exports array of plugins with configuration. 50 | * @type {Array} 51 | */ 52 | exports.default = [ 53 | /* ----------------------- 54 | Register inert 55 | ------------------------ */ 56 | { 57 | plugin: _inert2.default, 58 | options: {} 59 | }, 60 | 61 | /* ----------------------- 62 | Register vision 63 | ------------------------ */ 64 | { 65 | plugin: _vision2.default, 66 | options: {} 67 | }, 68 | 69 | /* ------------------ 70 | Register good 71 | ------------------ */ 72 | 73 | { 74 | plugin: _good2.default, 75 | options: { 76 | ops: { 77 | interval: 1000 78 | }, 79 | reporters: { 80 | myConsoleReporter: [{ 81 | module: 'good-squeeze', 82 | name: 'Squeeze', 83 | args: [{ log: '*', response: '*' }] 84 | }, { 85 | module: 'good-console' 86 | }, 'stdout'] 87 | } 88 | } 89 | }, 90 | 91 | /* --------------------------- 92 | Setting up the jwt auth. 93 | ---------------------------- */ 94 | { 95 | plugin: _auth2.default, 96 | options: {} 97 | }, 98 | 99 | /* --------------------------- 100 | Restfull Api's. 101 | ---------------------------- */ 102 | { 103 | plugin: _rest2.default, 104 | options: {} 105 | }, 106 | 107 | /* --------------------------- 108 | Init the index route. 109 | ---------------------------- */ 110 | { 111 | plugin: _main2.default, 112 | options: {} 113 | }, 114 | 115 | /* --------------------------- 116 | Init the Graphql Server. 117 | ---------------------------- */ 118 | { 119 | plugin: _graphql2.default, 120 | options: { 121 | path: '/gql', 122 | graphiql: app.debug, // isDevelopment 123 | graphiqlOptions: { 124 | passHeader: "'Authorization': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ3aGVuIjoxNTE0MjY5Mjk5NDEzLCJyb2xlIjoidXNlciIsImxhc3RMb2dpbiI6MTUxNDI2MDg1MDAwNiwidXNlcklkIjoiNWE0MWM5NTcyN2FmYjQwNmU3MzRlZTBiIiwiaWF0IjoxNTE0MjY5Mjk5LCJleHAiOjE1MjIwNDUyOTl9.VIyV8WcU_6E3cLW29913WkQk7xpoGkGCI4Qv8tmwsYwgMMCkWauROouo9KUZgBESmu74I9LhLSNU9hUGhm0DBg'" 125 | } 126 | } 127 | }]; -------------------------------------------------------------------------------- /dist/plugins/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | /* ------------------------------------------------------------------------------------------------ 7 | * @ description : Here we are creating the home page plugin. 8 | ------------------------------------------------------------------------------------------------- */ 9 | 10 | exports.default = { 11 | name: 'Main', 12 | version: '1.0.0', 13 | register: function register(server, options) { 14 | server.route({ path: '/{p*}', method: 'GET', handler: { file: './main.html' } }); 15 | } 16 | }; -------------------------------------------------------------------------------- /dist/plugins/rest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _api = require('../api'); 8 | 9 | var _api2 = _interopRequireDefault(_api); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12 | 13 | exports.default = { 14 | name: 'Rest', 15 | version: '1.0.0', 16 | register: function register(server, options) { 17 | server.route(_api2.default); 18 | } 19 | }; /* ------------------------------------------------------------------------------------------------ 20 | * @ description : Here we are creating the rest api's plugin. 21 | ------------------------------------------------------------------------------------------------- */ -------------------------------------------------------------------------------- /dist/schema/gql/book.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | var _books = [{ 7 | title: "Harry Potter and the Sorcerer's stone", 8 | author: 'J.K. Rowling' 9 | }, { 10 | title: 'Jurassic Park', 11 | author: 'Michael Crichton' 12 | }]; 13 | 14 | // The GraphQL schema in string form 15 | var typeDefs = exports.typeDefs = '\n type Query { books: [Book] }\n type Book { title: String, author: String }\n'; 16 | 17 | // The resolvers 18 | var resolvers = exports.resolvers = { 19 | Query: { books: function books() { 20 | return _books; 21 | } } 22 | }; -------------------------------------------------------------------------------- /dist/schema/gql/date.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.resolvers = exports.scalarType = exports.typeDefs = undefined; 7 | 8 | var _language = require('graphql/language'); 9 | 10 | var _isNumber = require('lodash/isNumber'); 11 | 12 | var _isNumber2 = _interopRequireDefault(_isNumber); 13 | 14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 15 | 16 | /* eslint-disable */ 17 | 18 | var typeDefs = exports.typeDefs = '\n\t\t\t\tscalar Date\n '; 19 | 20 | var scalarType = exports.scalarType = { 21 | description: 'Date custom scalar type', 22 | 23 | __parseValue: function __parseValue(value) { 24 | return new Date(value); // value from the client 25 | }, 26 | __serialize: function __serialize(value) { 27 | if ((0, _isNumber2.default)(value)) { 28 | return value; 29 | } else { 30 | return value.getTime(); // value sent to the client 31 | } 32 | }, 33 | __parseLiteral: function __parseLiteral(ast) { 34 | switch (ast.kind) { 35 | case _language.Kind.INT: 36 | case _language.Kind.FLOAT: 37 | return new Date(parseFloat(ast.value)); 38 | default: 39 | return null; 40 | } 41 | } 42 | }; 43 | 44 | var resolvers = exports.resolvers = { 45 | Date: scalarType 46 | }; -------------------------------------------------------------------------------- /dist/schema/gql/hello.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | var typeDefs = exports.typeDefs = "\n\t\t\t\t\ttype Query {\n\t\t\t\t\t say (\n \t\t\tsomething: String!\n \t\t\t): String\n\t\t\t\t\t}"; 7 | 8 | var resolvers = exports.resolvers = { 9 | Query: { 10 | say: function say(root, _ref, context) { 11 | var something = _ref.something; 12 | 13 | return "hello " + something; 14 | } 15 | } 16 | }; -------------------------------------------------------------------------------- /dist/schema/gql/indiecore.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.resolvers = exports.typeDefs = undefined; 7 | 8 | var _axios = require('axios'); 9 | 10 | var _axios2 = _interopRequireDefault(_axios); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } 15 | 16 | var typeDefs = exports.typeDefs = '\n # Business List\n type BusinessRecord {\n business_id: String\n name: String\n location: [String]\n display_address: String\n image_url: String\n types: [String]\n hasPhoto: Boolean\n user_count: Int\n distance: String\n }\n # Indiecore\n type Business {\n list: [BusinessRecord]\n places_count: String\n total_count: String\n }\n type Query {\n business (\n longitude: String!\n latitude: String!\n sort: String\n offset: String\n ): Business\n }'; 17 | 18 | var resolvers = exports.resolvers = { 19 | Query: { 20 | business: function () { 21 | var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(root, _ref, context) { 22 | var longitude = _ref.longitude, 23 | latitude = _ref.latitude, 24 | _ref$sort = _ref.sort, 25 | sort = _ref$sort === undefined ? '0' : _ref$sort, 26 | _ref$offset = _ref.offset, 27 | offset = _ref$offset === undefined ? '0' : _ref$offset; 28 | 29 | var _ref3, data; 30 | 31 | return regeneratorRuntime.wrap(function _callee$(_context) { 32 | while (1) { 33 | switch (_context.prev = _context.next) { 34 | case 0: 35 | _context.next = 2; 36 | return _axios2.default.post('http://indiecore.ignivadigital.net/api/v1/business/records', { 37 | userId: 'ogLXurwhuFpw4qj6x', 38 | token: 'RJuNYkab5G4ocWNSzOhEBcpgcqr2dyUFKIny7Ppib4E', 39 | longitude: longitude, 40 | latitude: latitude, 41 | sort: sort, 42 | offset: offset 43 | }); 44 | 45 | case 2: 46 | _ref3 = _context.sent; 47 | data = _ref3.data; 48 | 49 | if (!data.success) { 50 | _context.next = 6; 51 | break; 52 | } 53 | 54 | return _context.abrupt('return', data); 55 | 56 | case 6: 57 | throw new Error(data.error_text); 58 | 59 | case 7: 60 | case 'end': 61 | return _context.stop(); 62 | } 63 | } 64 | }, _callee, this); 65 | })); 66 | 67 | function business(_x, _x2, _x3) { 68 | return _ref2.apply(this, arguments); 69 | } 70 | 71 | return business; 72 | }() 73 | }, 74 | Business: { 75 | list: function list(_ref4) { 76 | var places_list = _ref4.places_list; 77 | 78 | return places_list; 79 | } 80 | } 81 | }; -------------------------------------------------------------------------------- /dist/schema/gql/json.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.resolvers = exports.scalarType = exports.typeDefs = undefined; 7 | 8 | var _language = require('graphql/language'); 9 | 10 | var typeDefs = exports.typeDefs = '\n scalar JSON\n '; /* eslint-disable */ 11 | 12 | var scalarType = exports.scalarType = { 13 | description: 'The `JSON` scalar type represents JSON values as specified by ' + '[ECMA-404](http://www.ecma-international.org/' + 'publications/files/ECMA-ST/ECMA-404.pdf).', 14 | 15 | __parseValue: function __parseValue(value) { 16 | return value; // value from the client 17 | }, 18 | __serialize: function __serialize(value) { 19 | return value; // value sent to the client 20 | }, 21 | __parseLiteral: function __parseLiteral(ast) { 22 | switch (ast.kind) { 23 | case _language.Kind.STRING: 24 | case _language.Kind.BOOLEAN: 25 | return ast.value; 26 | case _language.Kind.INT: 27 | case _language.Kind.FLOAT: 28 | return parseFloat(ast.value); 29 | case _language.Kind.OBJECT: 30 | { 31 | var value = Object.create(null); 32 | ast.fields.forEach(function (field) { 33 | value[field.name.value] = parseLiteral(field.value); 34 | }); 35 | 36 | return value; 37 | } 38 | case _language.Kind.LIST: 39 | return ast.values.map(parseLiteral); 40 | default: 41 | return null; 42 | } 43 | } 44 | }; 45 | 46 | var resolvers = exports.resolvers = { 47 | JSON: scalarType 48 | }; -------------------------------------------------------------------------------- /dist/schema/gql/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.resolvers = exports.typeDefs = undefined; 7 | 8 | var _graphqlSubscriptions = require('graphql-subscriptions'); 9 | 10 | var _user = require('../../controllers/user'); 11 | 12 | var _subscriptions = require('../../utilities/subscriptions'); 13 | 14 | var _subscriptions2 = _interopRequireDefault(_subscriptions); 15 | 16 | var _logger = require('../../utilities/logger'); 17 | 18 | var _logger2 = _interopRequireDefault(_logger); 19 | 20 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 21 | 22 | var SOMETHING_CHANGED_TOPIC = 'something_changed'; 23 | 24 | var typeDefs = exports.typeDefs = '\n type User {\n # Description for field\n _id: String\n fullName: String\n email: String!\n role: String!\n loginToken: String\n lastLogin: String\n }\n type Query {\n me:User\n }\n type Mutation {\n registerUser(\n fullName: String!\n email: String!\n password: String!\n role: String!\n ): User\n loginUser(\n email: String!\n password: String!\n ): User\n logoutUser: String!\n newUser: String!\n }\n type Subscription {\n newUser: String\n }\n '; 25 | 26 | var resolvers = exports.resolvers = { 27 | Query: { 28 | me: function me(root, payload, context) { 29 | if (context.auth.isAuthenticated) return context.auth.credentials.user; 30 | throw new Error(context.auth.message); 31 | } 32 | }, 33 | Mutation: { 34 | registerUser: _user.registerUser, 35 | loginUser: _user.loginUser, 36 | logoutUser: _user.logoutUser, 37 | newUser: function newUser(root, payload, context) { 38 | _subscriptions2.default.publish(SOMETHING_CHANGED_TOPIC, { newUser: 'Dev' }); 39 | return 'Dev'; 40 | } 41 | }, 42 | Subscription: { 43 | newUser: { 44 | // subscribe: () => pubsub.asyncIterator('something_changed'), 45 | // resolve: payload => { 46 | // return payload.newUser; 47 | // }, 48 | subscribe: (0, _graphqlSubscriptions.withFilter)(function () { 49 | return _subscriptions2.default.asyncIterator(SOMETHING_CHANGED_TOPIC); 50 | }, function (root, args, context) { 51 | _logger2.default.info('newUser', context); 52 | return true; 53 | }) 54 | } 55 | } 56 | }; -------------------------------------------------------------------------------- /dist/schema/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _graphqlTools = require('graphql-tools'); 8 | 9 | var _graphqlSchemaModules = require('graphql-schema-modules'); 10 | 11 | var _date = require('./gql/date'); 12 | 13 | var date = _interopRequireWildcard(_date); 14 | 15 | var _json = require('./gql/json'); 16 | 17 | var json = _interopRequireWildcard(_json); 18 | 19 | var _hello = require('./gql/hello'); 20 | 21 | var hello = _interopRequireWildcard(_hello); 22 | 23 | var _book = require('./gql/book'); 24 | 25 | var book = _interopRequireWildcard(_book); 26 | 27 | var _indiecore = require('./gql/indiecore'); 28 | 29 | var indiecore = _interopRequireWildcard(_indiecore); 30 | 31 | var _user = require('./gql/user'); 32 | 33 | var user = _interopRequireWildcard(_user); 34 | 35 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 36 | 37 | // **** Schema 38 | 39 | 40 | // **** Custom Scalar 41 | var _mergeModules = (0, _graphqlSchemaModules.mergeModules)([date, json, hello, book, indiecore, user]), 42 | typeDefs = _mergeModules.typeDefs, 43 | resolvers = _mergeModules.resolvers; 44 | 45 | var schema = (0, _graphqlTools.makeExecutableSchema)({ typeDefs: typeDefs, resolvers: resolvers }); 46 | 47 | exports.default = schema; -------------------------------------------------------------------------------- /dist/server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | require('./utilities/global'); 8 | 9 | var _hapi = require('hapi'); 10 | 11 | var _hapi2 = _interopRequireDefault(_hapi); 12 | 13 | var _config = require('config'); 14 | 15 | var _config2 = _interopRequireDefault(_config); 16 | 17 | var _plugins = require('./plugins'); 18 | 19 | var _plugins2 = _interopRequireDefault(_plugins); 20 | 21 | var _logger = require('./utilities/logger'); 22 | 23 | var _logger2 = _interopRequireDefault(_logger); 24 | 25 | var _rest = require('./utilities/rest'); 26 | 27 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 28 | 29 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* --------------------------------------------------------------------------------- 30 | * @ description : This is the server configration file. 31 | ---------------------------------------------------------------------------------- */ 32 | 33 | var app = _config2.default.get('app'); 34 | 35 | exports.default = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { 36 | var server; 37 | return regeneratorRuntime.wrap(function _callee$(_context) { 38 | while (1) { 39 | switch (_context.prev = _context.next) { 40 | case 0: 41 | server = new _hapi2.default.Server({ 42 | host: app.host, 43 | port: app.port, 44 | routes: { 45 | cors: { 46 | origin: ['*'], 47 | additionalHeaders: ['authorization'], 48 | additionalExposedHeaders: ['authorization'] 49 | }, 50 | validate: { 51 | failAction: _rest.failActionJoi 52 | } 53 | } 54 | }); 55 | _context.next = 3; 56 | return server.register(_plugins2.default); 57 | 58 | case 3: 59 | _context.prev = 3; 60 | _context.next = 6; 61 | return server.start(); 62 | 63 | case 6: 64 | _context.next = 11; 65 | break; 66 | 67 | case 8: 68 | _context.prev = 8; 69 | _context.t0 = _context['catch'](3); 70 | 71 | _logger2.default.info('Error while starting server: ' + _context.t0.message); 72 | 73 | case 11: 74 | 75 | _logger2.default.info('+++ Server running at: ' + server.info.uri); 76 | 77 | case 12: 78 | case 'end': 79 | return _context.stop(); 80 | } 81 | } 82 | }, _callee, undefined, [[3, 8]]); 83 | })); -------------------------------------------------------------------------------- /dist/services/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.logout = exports.login = exports.register = undefined; 7 | 8 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 9 | 10 | var _user = require('../collections/user'); 11 | 12 | var _user2 = _interopRequireDefault(_user); 13 | 14 | var _messages = require('../utilities/messages'); 15 | 16 | var _messages2 = _interopRequireDefault(_messages); 17 | 18 | var _universal = require('../utilities/universal'); 19 | 20 | var Universal = _interopRequireWildcard(_universal); 21 | 22 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 23 | 24 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 25 | 26 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* ----------------------------------------------------------------------- 27 | * @ description : This is the user service layer. 28 | ----------------------------------------------------------------------- */ 29 | 30 | // import * as Mail from '../utilities/mail'; 31 | // import logger from '../utilities/logger'; 32 | 33 | var register = exports.register = function () { 34 | var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(payload) { 35 | var data; 36 | return regeneratorRuntime.wrap(function _callee$(_context) { 37 | while (1) { 38 | switch (_context.prev = _context.next) { 39 | case 0: 40 | _context.next = 2; 41 | return _user2.default.checkEmail(payload.email); 42 | 43 | case 2: 44 | if (!_context.sent) { 45 | _context.next = 4; 46 | break; 47 | } 48 | 49 | throw new Error(_messages2.default.emailAlreadyExists); 50 | 51 | case 4: 52 | 53 | payload = _extends({}, payload, { 54 | password: Universal.encryptpassword(payload.password), 55 | verified: { token: Universal.generateRandom() } 56 | }); 57 | 58 | _context.next = 7; 59 | return _user2.default.register(payload); 60 | 61 | case 7: 62 | data = _context.sent; 63 | return _context.abrupt('return', { 64 | _id: data._id, 65 | role: data.role, 66 | fullName: data.fullName, 67 | email: data.email 68 | }); 69 | 70 | case 9: 71 | case 'end': 72 | return _context.stop(); 73 | } 74 | } 75 | }, _callee, undefined); 76 | })); 77 | 78 | return function register(_x) { 79 | return _ref.apply(this, arguments); 80 | }; 81 | }(); 82 | 83 | var login = exports.login = function () { 84 | var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(payload) { 85 | var userData, loginToken, data; 86 | return regeneratorRuntime.wrap(function _callee2$(_context2) { 87 | while (1) { 88 | switch (_context2.prev = _context2.next) { 89 | case 0: 90 | _context2.next = 2; 91 | return _user2.default.login(payload.email, Universal.encryptpassword(payload.password)); 92 | 93 | case 2: 94 | userData = _context2.sent; 95 | 96 | if (userData) { 97 | _context2.next = 5; 98 | break; 99 | } 100 | 101 | throw new Error(_messages2.default.invalidCredentials); 102 | 103 | case 5: 104 | // if (!userData.verified.status) throw new Error(Messages.userNotVerified); 105 | 106 | loginToken = Universal.generateToken({ 107 | when: Universal.getTimeStamp(), 108 | role: userData.role, 109 | lastLogin: userData.lastLogin, 110 | userId: userData._id 111 | }); 112 | _context2.next = 8; 113 | return _user2.default.onLoginDone(userData._id, payload, loginToken); 114 | 115 | case 8: 116 | data = _context2.sent; 117 | return _context2.abrupt('return', { 118 | _id: data._id, 119 | role: data.role, 120 | fullName: data.fullName, 121 | email: data.email, 122 | loginToken: data.loginToken[data.loginToken.length - 1].token, 123 | lastLogin: data.lastLogin 124 | }); 125 | 126 | case 10: 127 | case 'end': 128 | return _context2.stop(); 129 | } 130 | } 131 | }, _callee2, undefined); 132 | })); 133 | 134 | return function login(_x2) { 135 | return _ref2.apply(this, arguments); 136 | }; 137 | }(); 138 | 139 | var logout = exports.logout = function () { 140 | var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(payload) { 141 | return regeneratorRuntime.wrap(function _callee3$(_context3) { 142 | while (1) { 143 | switch (_context3.prev = _context3.next) { 144 | case 0: 145 | _context3.next = 2; 146 | return _user2.default.logout(payload.user._id, payload.token); 147 | 148 | case 2: 149 | return _context3.abrupt('return', _context3.sent); 150 | 151 | case 3: 152 | case 'end': 153 | return _context3.stop(); 154 | } 155 | } 156 | }, _callee3, undefined); 157 | })); 158 | 159 | return function logout(_x3) { 160 | return _ref3.apply(this, arguments); 161 | }; 162 | }(); -------------------------------------------------------------------------------- /dist/utilities/global.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* ----------------------------------------------------------------------- 4 | * @ description : Here defines all global functions. 5 | ----------------------------------------------------------------------- */ 6 | 7 | /************* Captilize first character ************/ 8 | String.prototype.capitalizeFirstLetter = function () { 9 | return this.charAt(0).toUpperCase() + this.slice(1); 10 | }; 11 | 12 | /************* Captilize first character of word ************/ 13 | String.prototype.capitalizeEachLetter = function () { 14 | return this.split(' ').map(function (word) { 15 | return word.capitalizeFirstLetter(); 16 | }).join(' '); 17 | }; -------------------------------------------------------------------------------- /dist/utilities/logger.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _bunyan = require('bunyan'); 8 | 9 | var _bunyan2 = _interopRequireDefault(_bunyan); 10 | 11 | var _config = require('config'); 12 | 13 | var _config2 = _interopRequireDefault(_config); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | // create a logger instance 18 | exports.default = new _bunyan2.default({ 19 | name: _config2.default.get('app.name'), 20 | level: _config2.default.get('app.logLevel'), 21 | serializers: _bunyan2.default.stdSerializers 22 | }); -------------------------------------------------------------------------------- /dist/utilities/mail.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.sendMail = exports.formatHTML = exports.subjects = undefined; 7 | 8 | var _nodemailer = require('nodemailer'); 9 | 10 | var _nodemailer2 = _interopRequireDefault(_nodemailer); 11 | 12 | var _nodemailerSmtpTransport = require('nodemailer-smtp-transport'); 13 | 14 | var _nodemailerSmtpTransport2 = _interopRequireDefault(_nodemailerSmtpTransport); 15 | 16 | var _fs = require('fs'); 17 | 18 | var _fs2 = _interopRequireDefault(_fs); 19 | 20 | var _path = require('path'); 21 | 22 | var _path2 = _interopRequireDefault(_path); 23 | 24 | var _util = require('util'); 25 | 26 | var _util2 = _interopRequireDefault(_util); 27 | 28 | var _config = require('config'); 29 | 30 | var _config2 = _interopRequireDefault(_config); 31 | 32 | var _logger = require('./logger'); 33 | 34 | var _logger2 = _interopRequireDefault(_logger); 35 | 36 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 37 | 38 | var _config$get = _config2.default.get('smtp'), 39 | smtpUser = _config$get.smtpUser, 40 | smtpPass = _config$get.smtpPass, 41 | smtpPort = _config$get.smtpPort, 42 | smtpServer = _config$get.smtpServer, 43 | mailFrom = _config$get.mailFrom; /* ----------------------------------------------------------------------- 44 | * @ description : Here initialising nodemailer transport for sending mails. 45 | ----------------------------------------------------------------------- */ 46 | 47 | var transporter = _nodemailer2.default.createTransport((0, _nodemailerSmtpTransport2.default)({ 48 | host: smtpServer, // hostname 49 | port: smtpPort, // port for secure SMTP 50 | auth: { 51 | user: smtpUser, 52 | pass: smtpPass 53 | } 54 | })); 55 | 56 | var subjects = exports.subjects = { 57 | userVerification: 'Verify Email', 58 | forgetPassword: 'Forget Password' 59 | }; 60 | 61 | var formatHTML = exports.formatHTML = function formatHTML(request) { 62 | var templatepath = _path2.default.join(__dirname, '../emailTemplates/'), 63 | emailTemplate = _fs2.default.readFileSync(_path2.default.resolve('' + templatepath + request.fileName), 'UTF-8'); 64 | 65 | /******** Replace dynamic values in email template. ********/ 66 | return _util2.default.format(emailTemplate, request.username, request.link); 67 | }; 68 | 69 | var sendMail = exports.sendMail = function sendMail(request, cb) { 70 | var options = { 71 | from: mailFrom, 72 | to: request.to, // list of receivers 73 | subject: request.subject, // Subject line 74 | // text: '', // plaintext body 75 | html: request.html // html body 76 | // replyTo: "" 77 | }; 78 | 79 | if (request.cc) { 80 | options.cc = request.cc; 81 | } 82 | if (request.replyTo) { 83 | options.replyTo = request.replyTo; 84 | } 85 | 86 | transporter.sendMail(options, function (error, info) { 87 | // send mail with defined transport object 88 | _logger2.default.info(error, info); 89 | cb(error, info); 90 | }); 91 | }; -------------------------------------------------------------------------------- /dist/utilities/messages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | /* ----------------------------------------------------------------------- 7 | * @ description : Main module to include all the messages used in project. 8 | ----------------------------------------------------------------------- */ 9 | 10 | exports.default = { 11 | accept: 'Accepted', 12 | confirm: 'Confirmed', 13 | say: function say(text) { 14 | return 'Hello ' + text; 15 | }, 16 | systemError: 'Technical error ! Please try again later.', 17 | userNameAlreadyExists: 'This Username is already registered.', 18 | emailAlreadyExists: 'This Email is already registered.', 19 | contactAlreadyExists: 'This contact number is already registered.', 20 | emailNotExists: 'Email is not registered with us.', 21 | phoneNumberNotExists: 'Phone Number not registered.', 22 | registerSuccess: 'Your account has been registered successfully.', 23 | tokenExpired: 'Session Expired.', 24 | tokenVerified: 'Token has been verified', 25 | sendOTP: 'A verification code has been sent to your Contact number.', 26 | forgetPassword: 'We have sent you an email on your registered email account to reset your password.', 27 | resetpassword: 'Your password has been reset successfully!', 28 | passwordUpdated: 'Your password has been successfully changed. Please login with new password to continue. Thanks!.', 29 | emailChanged: 'An OTP is sent to the registered email Id. Please use that to verify your email.', 30 | phoneNumChanged: 'An OTP is sent to the registered phone number. Please use that to verify your phone number.', 31 | emailUpdated: 'Email updated successfully.', 32 | loginSuccessfull: 'Logged in successfully.', 33 | logoutSuccessfull: 'Logged out successfully.', 34 | invalidCredentials: 'Invalid credentials.', 35 | accountNotConfirmed: 'Your account is not confirmed.Please confirm verification link sent your registered email.', 36 | profileUpdate: 'Profile successfully updated.', 37 | unauthorizedUser: 'You are not an authorized user for this action.', 38 | forgetPasswordEmail: 'An OTP is sent to the registered email Id. Please use that OTP to access your account.', 39 | contactUs: 'Your message has been sent successfully to admin.', 40 | otpVerified: 'OTP verified successfully.', 41 | userAuthenticated: 'User authenticated successfully.', 42 | userNotVerified: "You haven't verify your account. Please verify to proceed.", 43 | userBlocked: 'Your account has been blocked by Admin. Please contact admin for further queries.', 44 | verifyTokenSuccess: 'Your email has been successfully verified.', 45 | verifyTokenExpired: 'Token has been expired.' 46 | }; -------------------------------------------------------------------------------- /dist/utilities/rest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.failActionJoi = exports.failAction = exports.successAction = exports.authorization = exports.authContext = undefined; 7 | 8 | var _boom = require('boom'); 9 | 10 | var _boom2 = _interopRequireDefault(_boom); 11 | 12 | var _config = require('config'); 13 | 14 | var _config2 = _interopRequireDefault(_config); 15 | 16 | var _jsonwebtoken = require('jsonwebtoken'); 17 | 18 | var _jsonwebtoken2 = _interopRequireDefault(_jsonwebtoken); 19 | 20 | var _user = require('../collections/user'); 21 | 22 | var _user2 = _interopRequireDefault(_user); 23 | 24 | var _messages = require('./messages'); 25 | 26 | var _messages2 = _interopRequireDefault(_messages); 27 | 28 | var _logger = require('./logger'); 29 | 30 | var _logger2 = _interopRequireDefault(_logger); 31 | 32 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 33 | 34 | function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* ----------------------------------------------------------------------- 35 | * @ description : Here defines all rest functions. 36 | ----------------------------------------------------------------------- */ 37 | 38 | var _config$get = _config2.default.get('app'), 39 | jwtKey = _config$get.jwtKey; 40 | 41 | var authContext = exports.authContext = function () { 42 | var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(request) { 43 | var token, decoded, data, user; 44 | return regeneratorRuntime.wrap(function _callee$(_context) { 45 | while (1) { 46 | switch (_context.prev = _context.next) { 47 | case 0: 48 | token = request.headers['authorization']; 49 | decoded = {}; 50 | _context.prev = 2; 51 | 52 | decoded = _jsonwebtoken2.default.verify(token, jwtKey); 53 | _context.next = 9; 54 | break; 55 | 56 | case 6: 57 | _context.prev = 6; 58 | _context.t0 = _context['catch'](2); 59 | return _context.abrupt('return', { isAuthenticated: false, message: _messages2.default.tokenExpired }); 60 | 61 | case 9: 62 | _logger2.default.info('authorization', decoded); 63 | _context.next = 12; 64 | return _user2.default.checkToken(token); 65 | 66 | case 12: 67 | data = _context.sent; 68 | 69 | if (!data) { 70 | _context.next = 18; 71 | break; 72 | } 73 | 74 | user = { 75 | _id: data._id, 76 | role: data.role, 77 | fullName: data.fullName, 78 | email: data.email, 79 | loginToken: data.loginToken[data.loginToken.length - 1].token, 80 | lastLogin: data.lastLogin 81 | }; 82 | return _context.abrupt('return', { isAuthenticated: true, credentials: { user: user, token: token }, message: _messages2.default.tokenVerified }); 83 | 84 | case 18: 85 | return _context.abrupt('return', { isAuthenticated: false, message: _messages2.default.tokenExpired }); 86 | 87 | case 19: 88 | case 'end': 89 | return _context.stop(); 90 | } 91 | } 92 | }, _callee, undefined, [[2, 6]]); 93 | })); 94 | 95 | return function authContext(_x) { 96 | return _ref.apply(this, arguments); 97 | }; 98 | }(); 99 | 100 | var authorization = exports.authorization = function () { 101 | var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(request, h) { 102 | var token, decoded, user; 103 | return regeneratorRuntime.wrap(function _callee2$(_context2) { 104 | while (1) { 105 | switch (_context2.prev = _context2.next) { 106 | case 0: 107 | token = request.headers['authorization']; 108 | decoded = {}; 109 | _context2.prev = 2; 110 | 111 | decoded = _jsonwebtoken2.default.verify(token, jwtKey); 112 | _context2.next = 9; 113 | break; 114 | 115 | case 6: 116 | _context2.prev = 6; 117 | _context2.t0 = _context2['catch'](2); 118 | throw _boom2.default.unauthorized(_messages2.default.tokenExpired); 119 | 120 | case 9: 121 | _logger2.default.info('authorization', decoded); 122 | _context2.next = 12; 123 | return _user2.default.checkToken(token); 124 | 125 | case 12: 126 | user = _context2.sent; 127 | 128 | if (!user) { 129 | _context2.next = 17; 130 | break; 131 | } 132 | 133 | return _context2.abrupt('return', h.authenticated({ credentials: { user: user, token: token } })); 134 | 135 | case 17: 136 | throw _boom2.default.unauthorized(_messages2.default.tokenExpired); 137 | 138 | case 18: 139 | case 'end': 140 | return _context2.stop(); 141 | } 142 | } 143 | }, _callee2, undefined, [[2, 6]]); 144 | })); 145 | 146 | return function authorization(_x2, _x3) { 147 | return _ref2.apply(this, arguments); 148 | }; 149 | }(); 150 | 151 | var successAction = exports.successAction = function successAction(data) { 152 | var message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'OK'; 153 | return { 154 | statusCode: 200, 155 | message: message, 156 | data: data ? data : undefined 157 | }; 158 | }; 159 | 160 | var failAction = exports.failAction = function failAction(errorMessage) { 161 | throw _boom2.default.badRequest(errorMessage); 162 | }; 163 | 164 | var failActionJoi = exports.failActionJoi = function failActionJoi(request, h, error) { 165 | var errorMessage = ''; 166 | if (error.output.payload.message.indexOf('[') > -1) { 167 | errorMessage = error.output.payload.message.substr(error.output.payload.message.indexOf('[')); 168 | } else { 169 | errorMessage = error.output.payload.message; 170 | } 171 | errorMessage = errorMessage.replace(/"/g, ''); 172 | errorMessage = errorMessage.replace('[', ''); 173 | errorMessage = errorMessage.replace(']', ''); 174 | error.output.payload.message = errorMessage; 175 | delete error.output.payload.validation; 176 | throw _boom2.default.badRequest(errorMessage); 177 | }; -------------------------------------------------------------------------------- /dist/utilities/subscriptions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _graphqlSubscriptions = require('graphql-subscriptions'); 8 | 9 | exports.default = new _graphqlSubscriptions.PubSub(); -------------------------------------------------------------------------------- /dist/utilities/twilio.js: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------------- 2 | * @ description : This file represents the Twilio Messaging Module. 3 | --------------------------------------------------------------------------------- */ 4 | 5 | // import twilio from 'twilio'; 6 | // import config from 'config'; 7 | 8 | // const { sid, token } = config.get('twillio'); 9 | 10 | // const twilioObj = sid != '' && token != '' ? new twilio(sid, token) : null; 11 | 12 | // export default twilioObj; 13 | "use strict"; -------------------------------------------------------------------------------- /dist/utilities/universal.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.uploader = exports.imageFilter = exports.decodeToken = exports.generateToken = exports.generateRandom = exports.encryptpassword = exports.getTimeStamp = undefined; 7 | 8 | var _md = require('md5'); 9 | 10 | var _md2 = _interopRequireDefault(_md); 11 | 12 | var _jsonwebtoken = require('jsonwebtoken'); 13 | 14 | var _jsonwebtoken2 = _interopRequireDefault(_jsonwebtoken); 15 | 16 | var _config = require('config'); 17 | 18 | var _config2 = _interopRequireDefault(_config); 19 | 20 | var _fs = require('fs'); 21 | 22 | var _fs2 = _interopRequireDefault(_fs); 23 | 24 | var _slugify = require('slugify'); 25 | 26 | var _slugify2 = _interopRequireDefault(_slugify); 27 | 28 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 29 | 30 | var getTimeStamp = exports.getTimeStamp = function getTimeStamp() { 31 | return Date.now(); 32 | }; /* ----------------------------------------------------------------------- 33 | * @ description : Here defines all universal functions. 34 | ----------------------------------------------------------------------- */ 35 | 36 | var encryptpassword = exports.encryptpassword = function encryptpassword(request) { 37 | return (0, _md2.default)(request); 38 | }; 39 | 40 | var generateRandom = exports.generateRandom = function generateRandom() { 41 | var length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 32; 42 | var alphanumeric = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; 43 | 44 | var data = '', 45 | keys = ''; 46 | 47 | if (alphanumeric) { 48 | keys = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 49 | } else { 50 | keys = '0123456789'; 51 | } 52 | 53 | for (var i = 0; i < length; i++) { 54 | data += keys.charAt(Math.floor(Math.random() * keys.length)); 55 | } 56 | 57 | return data; 58 | }; 59 | 60 | var generateToken = exports.generateToken = function generateToken(data) { 61 | return _jsonwebtoken2.default.sign(data, _config2.default.app.jwtKey, { algorithm: _config2.default.app.jwtAlgo, expiresIn: '90d' }); 62 | }; 63 | 64 | var decodeToken = exports.decodeToken = function decodeToken(token) { 65 | return _jsonwebtoken2.default.verify(token, _config2.default.app.jwtKey); 66 | }; 67 | 68 | var imageFilter = exports.imageFilter = function imageFilter(fileName) { 69 | // accept image only 70 | if (!fileName.match(/\.(jpg|jpeg|png|gif)$/)) { 71 | return false; 72 | } 73 | 74 | return true; 75 | }; 76 | 77 | var uploader = exports.uploader = function uploader(file, options) { 78 | if (!file) throw new Error('no file(s)'); 79 | return Array.isArray(file) ? _filesHandler(file, options) : _fileHandler(file, options); 80 | }; 81 | 82 | var _fileHandler = function _fileHandler(file, options) { 83 | if (!file) throw new Error('No file'); 84 | 85 | if (options.fileFilter && !options.fileFilter(file.hapi.filename)) { 86 | throw new Error('Type not allowed'); 87 | } 88 | 89 | var fileName = (0, _slugify2.default)(generateRandom(5) + '_' + file.hapi.filename); 90 | var originalName = file.hapi.filename; 91 | var path = '' + options.dest + fileName; 92 | var fileStream = _fs2.default.createWriteStream(path); 93 | 94 | return new Promise(function (resolve, reject) { 95 | file.on('error', function (err) { 96 | reject(err); 97 | }); 98 | 99 | file.pipe(fileStream); 100 | 101 | file.on('end', function (err) { 102 | var fileDetails = { 103 | fileName: fileName, 104 | originalName: originalName, 105 | mimetype: file.hapi.headers['content-type'], 106 | size: _fs2.default.statSync(path).size 107 | }; 108 | 109 | resolve(fileDetails); 110 | }); 111 | }); 112 | }; 113 | 114 | var _filesHandler = function _filesHandler(files, options) { 115 | if (!files || !Array.isArray(files)) throw new Error('no files'); 116 | 117 | var promises = files.map(function (x) { 118 | return _fileHandler(x, options); 119 | }); 120 | return Promise.all(promises); 121 | }; -------------------------------------------------------------------------------- /emailTemplates/verifyEmail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mail 7 | 69 | 70 | 71 | 72 | 73 | 74 | 97 | 98 | 99 |
75 | 76 | 77 | 78 | 93 | 94 | 95 |
79 | 80 | 81 | 82 | 83 | 87 | 88 | 89 | 90 | 91 |
84 | 85 | 86 |
92 |
96 |
100 | 101 | 102 | 103 | 208 | 209 | 210 |
104 | 105 | 106 | 107 | 203 | 204 | 205 | 206 |
108 | 109 | 110 | 111 | 112 | 113 | 114 | 142 | 143 | 144 | 197 | 198 | 199 |
115 | 116 | 117 | 118 | 122 | 123 | 124 | 129 | 130 | 131 | 135 | 136 | 137 | 138 | 139 | 140 |
119 | Hi %s, 120 |

Greetings! 121 |
125 |
Welcome to Application. 126 |
Please click on the below link to verify your email. 127 |
128 |
132 |
Best, 133 |
Dev Team
134 |
141 |
145 | 146 | 147 | 148 | 149 | 154 | 155 | 156 | 194 | 195 |
150 | Find us on social media:

151 | 152 | 153 |
157 | 158 | 159 | 160 | 161 | 168 | 169 | 176 | 177 | 184 | 185 | 186 | 187 | 190 | 191 |
162 |
163 | 164 | 165 | 166 |
167 |
  170 |
171 | 172 | 173 | 174 |
175 |
  178 |
179 | 180 | 181 | 182 |
183 |
188 |   189 |
192 | 193 |
196 |
200 | 201 | 202 |
207 |
211 | 212 | -------------------------------------------------------------------------------- /main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hano 6 | 7 | 8 | 9 |
10 |

Hano GraphiQL Link.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------------- 2 | * @ description : This is the main startup server file to configure the application. 3 | ---------------------------------------------------------------------------------- */ 4 | 5 | import 'babel-polyfill'; 6 | import 'babel-core/register'; 7 | import configureDatabase from './db'; 8 | import configureServer from './server'; 9 | 10 | // creating REST API server connection. 11 | configureServer(); 12 | 13 | // create DB connection. 14 | configureDatabase(); 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hano", 3 | "version": "1.0.0", 4 | "description": "GraphQL, Hapi and Node Project For Scaleable Apps", 5 | "engines": { 6 | "node": ">=8.9.0" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/ignivalancy/hano-graphql.git" 11 | }, 12 | "keywords": ["node", "hapi", "js", "graphql", "mongo"], 13 | "bugs": { 14 | "url": "https://github.com/ignivalancy/hano-graphql/issues" 15 | }, 16 | "homepage": "https://github.com/ignivalancy/hano-graphql#readme", 17 | "dependencies": { 18 | "apn": "2.1.5", 19 | "apollo-errors": "^1.5.1", 20 | "apollo-server-hapi": "^1.3.1", 21 | "axios": "^0.17.1", 22 | "babel-core": "^6.26.0", 23 | "babel-polyfill": "^6.26.0", 24 | "bluebird": "^3.5.1", 25 | "boom": "^6.0.0", 26 | "config": "1.26.2", 27 | "fcm-node": "1.2.0", 28 | "good": "^8.0.0-rc1", 29 | "good-console": "^6.4.0", 30 | "good-squeeze": "^5.0.2", 31 | "graphql": "^0.11.7", 32 | "graphql-schema-modules": "0.0.2", 33 | "graphql-subscriptions": "^0.5.6", 34 | "graphql-tools": "^2.13.0", 35 | "hapi": "^17.1.1", 36 | "http-status": "1.0.1", 37 | "inert": "^5.0.1", 38 | "joi": "13.0.1", 39 | "jsonwebtoken": "8.1.0", 40 | "lodash": "^4.17.4", 41 | "md5": "2.2.1", 42 | "moment": "2.19.1", 43 | "mongoose": "^4.12.4", 44 | "nodemailer": "4.2.0", 45 | "nodemailer-smtp-transport": "2.7.4", 46 | "path": "^0.12.7", 47 | "slugify": "^1.2.8", 48 | "socket.io": "2.0.4", 49 | "stripe": "5.1.1", 50 | "subscriptions-transport-ws": "^0.9.4", 51 | "twilio": "3.9.0", 52 | "underscore": "1.8.3", 53 | "uuid": "^3.1.0", 54 | "vision": "^5.2.0" 55 | }, 56 | "devDependencies": { 57 | "babel-cli": "^6.26.0", 58 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 59 | "babel-preset-env": "^1.6.1", 60 | "bunyan": "^2.0.2", 61 | "eslint": "^4.13.1", 62 | "eslint-config-prettier": "^2.9.0", 63 | "eslint-config-standard": "^11.0.0-beta.0", 64 | "eslint-plugin-import": "^2.8.0", 65 | "eslint-plugin-node": "^5.2.1", 66 | "eslint-plugin-prettier": "^2.3.1", 67 | "eslint-plugin-promise": "^3.6.0", 68 | "eslint-plugin-standard": "^3.0.1", 69 | "husky": "^0.14.3", 70 | "lint-staged": "^5.0.0", 71 | "nodemon": "^1.12.1", 72 | "prettier": "^1.8.2" 73 | }, 74 | "main": "main.js", 75 | "scripts": { 76 | "start": "nodemon --exec babel-node -- main.js", 77 | "test": "echo \"Error: no test specified\" && exit 1", 78 | "build": "rm -rf dist && babel . -d dist --ignore node_modules", 79 | "serve": "node dist/main.js", 80 | "ri": "rm -rf node_modules && npm install", 81 | "lint": "./node_modules/.bin/eslint . --ext .js", 82 | "rp": "prettier --write \"**/*.json\" \"**/*.js\" \"!dist/**/*.js\"", 83 | "precommit": "npm run rp && lint-staged" 84 | }, 85 | "author": "Lancy Goyal", 86 | "email": "i.lancygoyal@gmail.com", 87 | "url": "https://lancygoyal.github.io", 88 | "license": "MIT" 89 | } 90 | -------------------------------------------------------------------------------- /plugins/auth.js: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------------------------------ 2 | * @ description : Here we are creating the auth plugin. 3 | ------------------------------------------------------------------------------------------------- */ 4 | 5 | import { authorization } from '../utilities/rest'; 6 | 7 | export default { 8 | name: 'Auth', 9 | version: '1.0.0', 10 | register: (server, options) => { 11 | const scheme = () => ({ 12 | authenticate: authorization 13 | }); 14 | server.auth.scheme('jwt', scheme); 15 | server.auth.strategy('jwt', 'jwt'); 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /plugins/graphql.js: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------------------------------ 2 | * @ description : Here we are creating the Graphql Plugin. 3 | ------------------------------------------------------------------------------------------------- */ 4 | 5 | import { graphqlHapi, graphiqlHapi } from 'apollo-server-hapi'; 6 | import { formatError } from 'apollo-errors'; 7 | import { SubscriptionServer } from 'subscriptions-transport-ws'; 8 | import { execute, subscribe } from 'graphql'; 9 | import { authContext } from '../utilities/rest'; 10 | import schema from '../schema'; 11 | import logger from '../utilities/logger'; 12 | 13 | export default { 14 | name: 'Graphql', 15 | version: '1.0.0', 16 | register: async ( 17 | server, 18 | { 19 | path = '/graphql', 20 | subscriptionsPath = '/subscriptions', 21 | graphiql = false, 22 | graphiqlPath = '/graphiql', 23 | graphiqlOptions 24 | } 25 | ) => { 26 | let subscriptionsEndpoint = `ws://${server.info.host}:${server.info.port}${subscriptionsPath}`; 27 | let plugins = [ 28 | { 29 | plugin: graphqlHapi, 30 | options: { 31 | path, 32 | graphqlOptions: async request => ({ 33 | context: { auth: await authContext(request) }, 34 | schema, 35 | formatError 36 | }), 37 | route: { 38 | cors: true 39 | } 40 | } 41 | } 42 | ]; 43 | 44 | if (graphiql) 45 | plugins.push({ 46 | plugin: graphiqlHapi, 47 | options: { 48 | path: graphiqlPath, 49 | graphiqlOptions: { 50 | endpointURL: path, 51 | ...graphiqlOptions, 52 | subscriptionsEndpoint 53 | } 54 | } 55 | }); 56 | 57 | // setup graphql server 58 | await server.register(plugins); 59 | 60 | // setup subscription server 61 | SubscriptionServer.create( 62 | { 63 | execute, 64 | subscribe, 65 | schema, 66 | onConnect: async ({ token }, webSocket) => { 67 | logger.info('+++ Subscription Connected'); 68 | 69 | // const userContext = authContext(token); 70 | 71 | // if (userContext.isAuthenticated) { 72 | // return { ...userContext }; 73 | // } 74 | 75 | // throw new Error(userContext.message); 76 | 77 | return; 78 | }, 79 | onDisconnect: webSocket => { 80 | logger.info('+++ Subscription Disconnected'); 81 | return; 82 | } 83 | }, 84 | { 85 | server: server.listener, 86 | path: subscriptionsPath 87 | } 88 | ); 89 | 90 | logger.info(`+++ GraphQL running at: ${server.info.uri}${path}`); 91 | logger.info(`+++ GraphQL Subscriptions running at: ${subscriptionsEndpoint}`); 92 | logger.info(`+++ GraphiQL running at: ${server.info.uri}${graphiqlPath}`); 93 | } 94 | }; 95 | -------------------------------------------------------------------------------- /plugins/index.js: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------- 2 | * @ description : Here config all hapi plugIns and custom plugIns. 3 | ----------------------------------------------------------------------- */ 4 | 5 | import Inert from 'inert'; 6 | import Vision from 'vision'; 7 | import Good from 'good'; 8 | import config from 'config'; 9 | // import Pack from '../package.json'; 10 | import Auth from './auth'; 11 | import Rest from './rest'; 12 | import Main from './main'; 13 | import Graphql from './graphql'; 14 | 15 | const app = config.get('app'); 16 | 17 | /** 18 | * exports array of plugins with configuration. 19 | * @type {Array} 20 | */ 21 | export default [ 22 | /* ----------------------- 23 | Register inert 24 | ------------------------ */ 25 | { 26 | plugin: Inert, 27 | options: {} 28 | }, 29 | 30 | /* ----------------------- 31 | Register vision 32 | ------------------------ */ 33 | { 34 | plugin: Vision, 35 | options: {} 36 | }, 37 | 38 | /* ------------------ 39 | Register good 40 | ------------------ */ 41 | 42 | { 43 | plugin: Good, 44 | options: { 45 | ops: { 46 | interval: 1000 47 | }, 48 | reporters: { 49 | myConsoleReporter: [ 50 | { 51 | module: 'good-squeeze', 52 | name: 'Squeeze', 53 | args: [{ log: '*', response: '*' }] 54 | }, 55 | { 56 | module: 'good-console' 57 | }, 58 | 'stdout' 59 | ] 60 | } 61 | } 62 | }, 63 | 64 | /* --------------------------- 65 | Setting up the jwt auth. 66 | ---------------------------- */ 67 | { 68 | plugin: Auth, 69 | options: {} 70 | }, 71 | 72 | /* --------------------------- 73 | Restfull Api's. 74 | ---------------------------- */ 75 | { 76 | plugin: Rest, 77 | options: {} 78 | }, 79 | 80 | /* --------------------------- 81 | Init the index route. 82 | ---------------------------- */ 83 | { 84 | plugin: Main, 85 | options: {} 86 | }, 87 | 88 | /* --------------------------- 89 | Init the Graphql Server. 90 | ---------------------------- */ 91 | { 92 | plugin: Graphql, 93 | options: { 94 | path: '/gql', 95 | graphiql: app.debug, // isDevelopment 96 | graphiqlOptions: { 97 | passHeader: 98 | "'Authorization': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ3aGVuIjoxNTE0MjY5Mjk5NDEzLCJyb2xlIjoidXNlciIsImxhc3RMb2dpbiI6MTUxNDI2MDg1MDAwNiwidXNlcklkIjoiNWE0MWM5NTcyN2FmYjQwNmU3MzRlZTBiIiwiaWF0IjoxNTE0MjY5Mjk5LCJleHAiOjE1MjIwNDUyOTl9.VIyV8WcU_6E3cLW29913WkQk7xpoGkGCI4Qv8tmwsYwgMMCkWauROouo9KUZgBESmu74I9LhLSNU9hUGhm0DBg'" 99 | } 100 | } 101 | } 102 | ]; 103 | -------------------------------------------------------------------------------- /plugins/main.js: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------------------------------ 2 | * @ description : Here we are creating the home page plugin. 3 | ------------------------------------------------------------------------------------------------- */ 4 | 5 | export default { 6 | name: 'Main', 7 | version: '1.0.0', 8 | register: (server, options) => { 9 | server.route({ path: '/{p*}', method: 'GET', handler: { file: './main.html' } }); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /plugins/rest.js: -------------------------------------------------------------------------------- 1 | /* ------------------------------------------------------------------------------------------------ 2 | * @ description : Here we are creating the rest api's plugin. 3 | ------------------------------------------------------------------------------------------------- */ 4 | 5 | import api from '../api'; 6 | 7 | export default { 8 | name: 'Rest', 9 | version: '1.0.0', 10 | register: (server, options) => { 11 | server.route(api); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /private/info.txt: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------- 2 | 3 | * In this folder we are storing the certificates like APN etc. 4 | 5 | ---------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /schema/gql/book.js: -------------------------------------------------------------------------------- 1 | const books = [ 2 | { 3 | title: "Harry Potter and the Sorcerer's stone", 4 | author: 'J.K. Rowling' 5 | }, 6 | { 7 | title: 'Jurassic Park', 8 | author: 'Michael Crichton' 9 | } 10 | ]; 11 | 12 | // The GraphQL schema in string form 13 | export const typeDefs = ` 14 | type Query { books: [Book] } 15 | type Book { title: String, author: String } 16 | `; 17 | 18 | // The resolvers 19 | export const resolvers = { 20 | Query: { books: () => books } 21 | }; 22 | -------------------------------------------------------------------------------- /schema/gql/date.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import { Kind } from 'graphql/language'; 4 | import isNumber from 'lodash/isNumber'; 5 | 6 | export const typeDefs = ` 7 | scalar Date 8 | `; 9 | 10 | export const scalarType = { 11 | description: 'Date custom scalar type', 12 | 13 | __parseValue(value) { 14 | return new Date(value); // value from the client 15 | }, 16 | __serialize(value) { 17 | if (isNumber(value)) { 18 | return value; 19 | } else { 20 | return value.getTime(); // value sent to the client 21 | } 22 | }, 23 | __parseLiteral(ast) { 24 | switch (ast.kind) { 25 | case Kind.INT: 26 | case Kind.FLOAT: 27 | return new Date(parseFloat(ast.value)); 28 | default: 29 | return null; 30 | } 31 | } 32 | }; 33 | 34 | export const resolvers = { 35 | Date: scalarType 36 | }; 37 | -------------------------------------------------------------------------------- /schema/gql/hello.js: -------------------------------------------------------------------------------- 1 | export const typeDefs = ` 2 | type Query { 3 | say ( 4 | something: String! 5 | ): String 6 | }`; 7 | 8 | export const resolvers = { 9 | Query: { 10 | say(root, { something }, context) { 11 | return `hello ${something}`; 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /schema/gql/indiecore.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export const typeDefs = ` 4 | # Business List 5 | type BusinessRecord { 6 | business_id: String 7 | name: String 8 | location: [String] 9 | display_address: String 10 | image_url: String 11 | types: [String] 12 | hasPhoto: Boolean 13 | user_count: Int 14 | distance: String 15 | } 16 | # Indiecore 17 | type Business { 18 | list: [BusinessRecord] 19 | places_count: String 20 | total_count: String 21 | } 22 | type Query { 23 | business ( 24 | longitude: String! 25 | latitude: String! 26 | sort: String 27 | offset: String 28 | ): Business 29 | }`; 30 | 31 | export const resolvers = { 32 | Query: { 33 | async business(root, { longitude, latitude, sort = '0', offset = '0' }, context) { 34 | const { data } = await axios.post( 35 | `http://indiecore.ignivadigital.net/api/v1/business/records`, 36 | { 37 | userId: 'ogLXurwhuFpw4qj6x', 38 | token: 'RJuNYkab5G4ocWNSzOhEBcpgcqr2dyUFKIny7Ppib4E', 39 | longitude, 40 | latitude, 41 | sort, 42 | offset 43 | } 44 | ); 45 | 46 | if (data.success) return data; 47 | 48 | throw new Error(data.error_text); 49 | } 50 | }, 51 | Business: { 52 | list({ places_list }) { 53 | return places_list; 54 | } 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /schema/gql/json.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | 3 | import { Kind } from 'graphql/language'; 4 | 5 | export const typeDefs = ` 6 | scalar JSON 7 | `; 8 | 9 | export const scalarType = { 10 | description: 11 | 'The `JSON` scalar type represents JSON values as specified by ' + 12 | '[ECMA-404](http://www.ecma-international.org/' + 13 | 'publications/files/ECMA-ST/ECMA-404.pdf).', 14 | 15 | __parseValue(value) { 16 | return value; // value from the client 17 | }, 18 | __serialize(value) { 19 | return value; // value sent to the client 20 | }, 21 | __parseLiteral(ast) { 22 | switch (ast.kind) { 23 | case Kind.STRING: 24 | case Kind.BOOLEAN: 25 | return ast.value; 26 | case Kind.INT: 27 | case Kind.FLOAT: 28 | return parseFloat(ast.value); 29 | case Kind.OBJECT: { 30 | const value = Object.create(null); 31 | ast.fields.forEach(field => { 32 | value[field.name.value] = parseLiteral(field.value); 33 | }); 34 | 35 | return value; 36 | } 37 | case Kind.LIST: 38 | return ast.values.map(parseLiteral); 39 | default: 40 | return null; 41 | } 42 | } 43 | }; 44 | 45 | export const resolvers = { 46 | JSON: scalarType 47 | }; 48 | -------------------------------------------------------------------------------- /schema/gql/user.js: -------------------------------------------------------------------------------- 1 | import { withFilter } from 'graphql-subscriptions'; 2 | import { registerUser, loginUser, logoutUser } from '../../controllers/user'; 3 | import pubsub from '../../utilities/subscriptions'; 4 | import logger from '../../utilities/logger'; 5 | 6 | const SOMETHING_CHANGED_TOPIC = 'something_changed'; 7 | 8 | export const typeDefs = ` 9 | type User { 10 | # Description for field 11 | _id: String 12 | fullName: String 13 | email: String! 14 | role: String! 15 | loginToken: String 16 | lastLogin: String 17 | } 18 | type Query { 19 | me:User 20 | } 21 | type Mutation { 22 | registerUser( 23 | fullName: String! 24 | email: String! 25 | password: String! 26 | role: String! 27 | ): User 28 | loginUser( 29 | email: String! 30 | password: String! 31 | ): User 32 | logoutUser: String! 33 | newUser: String! 34 | } 35 | type Subscription { 36 | newUser: String 37 | } 38 | `; 39 | 40 | export const resolvers = { 41 | Query: { 42 | me(root, payload, context) { 43 | if (context.auth.isAuthenticated) return context.auth.credentials.user; 44 | throw new Error(context.auth.message); 45 | } 46 | }, 47 | Mutation: { 48 | registerUser, 49 | loginUser, 50 | logoutUser, 51 | newUser(root, payload, context) { 52 | pubsub.publish(SOMETHING_CHANGED_TOPIC, { newUser: 'Dev' }); 53 | return 'Dev'; 54 | } 55 | }, 56 | Subscription: { 57 | newUser: { 58 | // subscribe: () => pubsub.asyncIterator('something_changed'), 59 | // resolve: payload => { 60 | // return payload.newUser; 61 | // }, 62 | subscribe: withFilter( 63 | () => pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC), 64 | (root, args, context) => { 65 | logger.info('newUser', context); 66 | return true; 67 | } 68 | ) 69 | } 70 | } 71 | }; 72 | -------------------------------------------------------------------------------- /schema/index.js: -------------------------------------------------------------------------------- 1 | import { makeExecutableSchema } from 'graphql-tools'; 2 | import { mergeModules } from 'graphql-schema-modules'; 3 | 4 | // **** Custom Scalar 5 | import * as date from './gql/date'; 6 | import * as json from './gql/json'; 7 | // **** Schema 8 | import * as hello from './gql/hello'; 9 | import * as book from './gql/book'; 10 | import * as indiecore from './gql/indiecore'; 11 | import * as user from './gql/user'; 12 | 13 | const { typeDefs, resolvers } = mergeModules([date, json, hello, book, indiecore, user]); 14 | 15 | const schema = makeExecutableSchema({ typeDefs, resolvers }); 16 | 17 | export default schema; 18 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | /* --------------------------------------------------------------------------------- 2 | * @ description : This is the server configration file. 3 | ---------------------------------------------------------------------------------- */ 4 | 5 | import './utilities/global'; 6 | import Hapi from 'hapi'; 7 | import config from 'config'; 8 | import plugins from './plugins'; 9 | import logger from './utilities/logger'; 10 | import { failActionJoi } from './utilities/rest'; 11 | 12 | const app = config.get('app'); 13 | 14 | export default async () => { 15 | const server = new Hapi.Server({ 16 | host: app.host, 17 | port: app.port, 18 | routes: { 19 | cors: { 20 | origin: ['*'], 21 | additionalHeaders: ['authorization'], 22 | additionalExposedHeaders: ['authorization'] 23 | }, 24 | validate: { 25 | failAction: failActionJoi 26 | } 27 | } 28 | }); 29 | 30 | await server.register(plugins); 31 | 32 | try { 33 | await server.start(); 34 | } catch (err) { 35 | logger.info(`Error while starting server: ${err.message}`); 36 | } 37 | 38 | logger.info(`+++ Server running at: ${server.info.uri}`); 39 | }; 40 | -------------------------------------------------------------------------------- /services/user.js: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | * @ description : This is the user service layer. 3 | ----------------------------------------------------------------------- */ 4 | 5 | import User from '../collections/user'; 6 | import Messages from '../utilities/messages'; 7 | import * as Universal from '../utilities/universal'; 8 | // import * as Mail from '../utilities/mail'; 9 | // import logger from '../utilities/logger'; 10 | 11 | export const register = async payload => { 12 | if (await User.checkEmail(payload.email)) throw new Error(Messages.emailAlreadyExists); 13 | 14 | payload = { 15 | ...payload, 16 | password: Universal.encryptpassword(payload.password), 17 | verified: { token: Universal.generateRandom() } 18 | }; 19 | 20 | const data = await User.register(payload); 21 | 22 | // const username = data.fullName.capitalizeEachLetter(), 23 | // link = `account-verification/${data.verified.token}`; 24 | 25 | // const sendStr = Mail.formatHTML({ fileName: 'verifyEmail.html', fullName, link }); 26 | 27 | // const emailData = { 28 | // to: data.email, 29 | // subject: Mail.subjects.userVerification, 30 | // html: sendStr 31 | // }; 32 | 33 | // Mail.sendMail(emailData, function(err, res) { 34 | // if (err) logger.log('-----@@----- Error at sending verify mail to user -----@@-----', err); 35 | // else logger.log('-----@@----- Response at sending verify mail to user -----@@-----', res); 36 | // }); 37 | 38 | return { 39 | _id: data._id, 40 | role: data.role, 41 | fullName: data.fullName, 42 | email: data.email 43 | }; 44 | }; 45 | 46 | export const login = async payload => { 47 | const userData = await User.login(payload.email, Universal.encryptpassword(payload.password)); 48 | if (!userData) throw new Error(Messages.invalidCredentials); 49 | // if (!userData.verified.status) throw new Error(Messages.userNotVerified); 50 | 51 | let loginToken = Universal.generateToken({ 52 | when: Universal.getTimeStamp(), 53 | role: userData.role, 54 | lastLogin: userData.lastLogin, 55 | userId: userData._id 56 | }); 57 | 58 | const data = await User.onLoginDone(userData._id, payload, loginToken); 59 | 60 | return { 61 | _id: data._id, 62 | role: data.role, 63 | fullName: data.fullName, 64 | email: data.email, 65 | loginToken: data.loginToken[data.loginToken.length - 1].token, 66 | lastLogin: data.lastLogin 67 | }; 68 | }; 69 | 70 | export const logout = async payload => { 71 | return await User.logout(payload.user._id, payload.token); 72 | }; 73 | -------------------------------------------------------------------------------- /updated_modules/good-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ignivalancy/hano-graphql/6994cfcfef0d58389d14a7ba1c261c8a5f6871c3/updated_modules/good-master.zip -------------------------------------------------------------------------------- /utilities/global.js: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | * @ description : Here defines all global functions. 3 | ----------------------------------------------------------------------- */ 4 | 5 | /************* Captilize first character ************/ 6 | String.prototype.capitalizeFirstLetter = function() { 7 | return this.charAt(0).toUpperCase() + this.slice(1); 8 | }; 9 | 10 | /************* Captilize first character of word ************/ 11 | String.prototype.capitalizeEachLetter = function() { 12 | return this.split(' ') 13 | .map(function(word) { 14 | return word.capitalizeFirstLetter(); 15 | }) 16 | .join(' '); 17 | }; 18 | -------------------------------------------------------------------------------- /utilities/logger.js: -------------------------------------------------------------------------------- 1 | import Logger from 'bunyan'; 2 | import config from 'config'; 3 | 4 | // create a logger instance 5 | export default new Logger({ 6 | name: config.get('app.name'), 7 | level: config.get('app.logLevel'), 8 | serializers: Logger.stdSerializers 9 | }); 10 | -------------------------------------------------------------------------------- /utilities/mail.js: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | * @ description : Here initialising nodemailer transport for sending mails. 3 | ----------------------------------------------------------------------- */ 4 | 5 | import nodemailer from 'nodemailer'; 6 | import smtpTransport from 'nodemailer-smtp-transport'; 7 | import fs from 'fs'; 8 | import path from 'path'; 9 | import util from 'util'; 10 | import config from 'config'; 11 | import logger from './logger'; 12 | 13 | const { smtpUser, smtpPass, smtpPort, smtpServer, mailFrom } = config.get('smtp'); 14 | 15 | const transporter = nodemailer.createTransport( 16 | smtpTransport({ 17 | host: smtpServer, // hostname 18 | port: smtpPort, // port for secure SMTP 19 | auth: { 20 | user: smtpUser, 21 | pass: smtpPass 22 | } 23 | }) 24 | ); 25 | 26 | export const subjects = { 27 | userVerification: 'Verify Email', 28 | forgetPassword: 'Forget Password' 29 | }; 30 | 31 | export const formatHTML = request => { 32 | const templatepath = path.join(__dirname, '../emailTemplates/'), 33 | emailTemplate = fs.readFileSync(path.resolve(`${templatepath}${request.fileName}`), 'UTF-8'); 34 | 35 | /******** Replace dynamic values in email template. ********/ 36 | return util.format(emailTemplate, request.username, request.link); 37 | }; 38 | 39 | export const sendMail = (request, cb) => { 40 | let options = { 41 | from: mailFrom, 42 | to: request.to, // list of receivers 43 | subject: request.subject, // Subject line 44 | // text: '', // plaintext body 45 | html: request.html // html body 46 | // replyTo: "" 47 | }; 48 | 49 | if (request.cc) { 50 | options.cc = request.cc; 51 | } 52 | if (request.replyTo) { 53 | options.replyTo = request.replyTo; 54 | } 55 | 56 | transporter.sendMail(options, function(error, info) { 57 | // send mail with defined transport object 58 | logger.info(error, info); 59 | cb(error, info); 60 | }); 61 | }; 62 | -------------------------------------------------------------------------------- /utilities/messages.js: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | * @ description : Main module to include all the messages used in project. 3 | ----------------------------------------------------------------------- */ 4 | 5 | export default { 6 | accept: 'Accepted', 7 | confirm: 'Confirmed', 8 | say: function(text) { 9 | return `Hello ${text}`; 10 | }, 11 | systemError: 'Technical error ! Please try again later.', 12 | userNameAlreadyExists: 'This Username is already registered.', 13 | emailAlreadyExists: 'This Email is already registered.', 14 | contactAlreadyExists: 'This contact number is already registered.', 15 | emailNotExists: 'Email is not registered with us.', 16 | phoneNumberNotExists: 'Phone Number not registered.', 17 | registerSuccess: 'Your account has been registered successfully.', 18 | tokenExpired: 'Session Expired.', 19 | tokenVerified: 'Token has been verified', 20 | sendOTP: 'A verification code has been sent to your Contact number.', 21 | forgetPassword: 22 | 'We have sent you an email on your registered email account to reset your password.', 23 | resetpassword: 'Your password has been reset successfully!', 24 | passwordUpdated: 25 | 'Your password has been successfully changed. Please login with new password to continue. Thanks!.', 26 | emailChanged: 'An OTP is sent to the registered email Id. Please use that to verify your email.', 27 | phoneNumChanged: 28 | 'An OTP is sent to the registered phone number. Please use that to verify your phone number.', 29 | emailUpdated: 'Email updated successfully.', 30 | loginSuccessfull: 'Logged in successfully.', 31 | logoutSuccessfull: 'Logged out successfully.', 32 | invalidCredentials: 'Invalid credentials.', 33 | accountNotConfirmed: 34 | 'Your account is not confirmed.Please confirm verification link sent your registered email.', 35 | profileUpdate: 'Profile successfully updated.', 36 | unauthorizedUser: 'You are not an authorized user for this action.', 37 | forgetPasswordEmail: 38 | 'An OTP is sent to the registered email Id. Please use that OTP to access your account.', 39 | contactUs: 'Your message has been sent successfully to admin.', 40 | otpVerified: 'OTP verified successfully.', 41 | userAuthenticated: 'User authenticated successfully.', 42 | userNotVerified: "You haven't verify your account. Please verify to proceed.", 43 | userBlocked: 'Your account has been blocked by Admin. Please contact admin for further queries.', 44 | verifyTokenSuccess: 'Your email has been successfully verified.', 45 | verifyTokenExpired: 'Token has been expired.' 46 | }; 47 | -------------------------------------------------------------------------------- /utilities/rest.js: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | * @ description : Here defines all rest functions. 3 | ----------------------------------------------------------------------- */ 4 | 5 | import Boom from 'boom'; 6 | import config from 'config'; 7 | import jwt from 'jsonwebtoken'; 8 | import User from '../collections/user'; 9 | import Messages from './messages'; 10 | import logger from './logger'; 11 | 12 | const { jwtKey } = config.get('app'); 13 | 14 | export const authContext = async request => { 15 | const token = request.headers['authorization']; 16 | let decoded = {}; 17 | try { 18 | decoded = jwt.verify(token, jwtKey); 19 | } catch (err) { 20 | return { isAuthenticated: false, message: Messages.tokenExpired }; 21 | } 22 | logger.info('authorization', decoded); 23 | const data = await User.checkToken(token); 24 | if (data) { 25 | const user = { 26 | _id: data._id, 27 | role: data.role, 28 | fullName: data.fullName, 29 | email: data.email, 30 | loginToken: data.loginToken[data.loginToken.length - 1].token, 31 | lastLogin: data.lastLogin 32 | }; 33 | return { isAuthenticated: true, credentials: { user, token }, message: Messages.tokenVerified }; 34 | } else return { isAuthenticated: false, message: Messages.tokenExpired }; 35 | }; 36 | 37 | export const authorization = async (request, h) => { 38 | const token = request.headers['authorization']; 39 | let decoded = {}; 40 | try { 41 | decoded = jwt.verify(token, jwtKey); 42 | } catch (err) { 43 | throw Boom.unauthorized(Messages.tokenExpired); 44 | } 45 | logger.info('authorization', decoded); 46 | const user = await User.checkToken(token); 47 | if (user) return h.authenticated({ credentials: { user, token } }); 48 | else throw Boom.unauthorized(Messages.tokenExpired); 49 | }; 50 | 51 | export const successAction = (data, message = 'OK') => ({ 52 | statusCode: 200, 53 | message, 54 | data: data ? data : undefined 55 | }); 56 | 57 | export const failAction = errorMessage => { 58 | throw Boom.badRequest(errorMessage); 59 | }; 60 | 61 | export const failActionJoi = (request, h, error) => { 62 | let errorMessage = ''; 63 | if (error.output.payload.message.indexOf('[') > -1) { 64 | errorMessage = error.output.payload.message.substr(error.output.payload.message.indexOf('[')); 65 | } else { 66 | errorMessage = error.output.payload.message; 67 | } 68 | errorMessage = errorMessage.replace(/"/g, ''); 69 | errorMessage = errorMessage.replace('[', ''); 70 | errorMessage = errorMessage.replace(']', ''); 71 | error.output.payload.message = errorMessage; 72 | delete error.output.payload.validation; 73 | throw Boom.badRequest(errorMessage); 74 | }; 75 | -------------------------------------------------------------------------------- /utilities/subscriptions.js: -------------------------------------------------------------------------------- 1 | import { PubSub } from 'graphql-subscriptions'; 2 | 3 | export default new PubSub(); 4 | -------------------------------------------------------------------------------- /utilities/twilio.js: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------------- 2 | * @ description : This file represents the Twilio Messaging Module. 3 | --------------------------------------------------------------------------------- */ 4 | 5 | // import twilio from 'twilio'; 6 | // import config from 'config'; 7 | 8 | // const { sid, token } = config.get('twillio'); 9 | 10 | // const twilioObj = sid != '' && token != '' ? new twilio(sid, token) : null; 11 | 12 | // export default twilioObj; 13 | -------------------------------------------------------------------------------- /utilities/universal.js: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------- 2 | * @ description : Here defines all universal functions. 3 | ----------------------------------------------------------------------- */ 4 | 5 | import md5 from 'md5'; 6 | import jwt from 'jsonwebtoken'; 7 | import config from 'config'; 8 | import fs from 'fs'; 9 | import slugify from 'slugify'; 10 | 11 | export const getTimeStamp = () => { 12 | return Date.now(); 13 | }; 14 | 15 | export const encryptpassword = request => md5(request); 16 | 17 | export const generateRandom = (length = 32, alphanumeric = true) => { 18 | let data = '', 19 | keys = ''; 20 | 21 | if (alphanumeric) { 22 | keys = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 23 | } else { 24 | keys = '0123456789'; 25 | } 26 | 27 | for (let i = 0; i < length; i++) { 28 | data += keys.charAt(Math.floor(Math.random() * keys.length)); 29 | } 30 | 31 | return data; 32 | }; 33 | 34 | export const generateToken = data => 35 | jwt.sign(data, config.app.jwtKey, { algorithm: config.app.jwtAlgo, expiresIn: '90d' }); 36 | 37 | export const decodeToken = token => jwt.verify(token, config.app.jwtKey); 38 | 39 | export const imageFilter = fileName => { 40 | // accept image only 41 | if (!fileName.match(/\.(jpg|jpeg|png|gif)$/)) { 42 | return false; 43 | } 44 | 45 | return true; 46 | }; 47 | 48 | export const uploader = (file, options) => { 49 | if (!file) throw new Error('no file(s)'); 50 | return Array.isArray(file) ? _filesHandler(file, options) : _fileHandler(file, options); 51 | }; 52 | 53 | const _fileHandler = function(file, options) { 54 | if (!file) throw new Error('No file'); 55 | 56 | if (options.fileFilter && !options.fileFilter(file.hapi.filename)) { 57 | throw new Error('Type not allowed'); 58 | } 59 | 60 | const fileName = slugify(`${generateRandom(5)}_${file.hapi.filename}`); 61 | const originalName = file.hapi.filename; 62 | const path = `${options.dest}${fileName}`; 63 | const fileStream = fs.createWriteStream(path); 64 | 65 | return new Promise((resolve, reject) => { 66 | file.on('error', function(err) { 67 | reject(err); 68 | }); 69 | 70 | file.pipe(fileStream); 71 | 72 | file.on('end', function(err) { 73 | const fileDetails = { 74 | fileName, 75 | originalName, 76 | mimetype: file.hapi.headers['content-type'], 77 | size: fs.statSync(path).size 78 | }; 79 | 80 | resolve(fileDetails); 81 | }); 82 | }); 83 | }; 84 | 85 | const _filesHandler = (files, options) => { 86 | if (!files || !Array.isArray(files)) throw new Error('no files'); 87 | 88 | const promises = files.map(x => _fileHandler(x, options)); 89 | return Promise.all(promises); 90 | }; 91 | --------------------------------------------------------------------------------