├── .env.example ├── .gitignore ├── Controllers ├── facebookSignInController.js ├── googleSignInController.js ├── userLoginController.js ├── userOnHomepageController.js ├── userRegisterController.js └── userTransactionsController.js ├── Models ├── db │ └── fadb.db └── user.service.js ├── Public ├── fbSignIn.js ├── googleSignIn.js ├── home.js ├── login.css ├── login.js ├── register.js └── signOut.js ├── Routes ├── login.js ├── oAuthSignIn.js ├── onHome.js ├── paymentRoutes.js └── register.js ├── dbrunonce.js ├── index.js ├── package-lock.json ├── package.json ├── readme.md ├── tokenauth └── tokenvalidation.js └── views ├── home.ejs ├── login.ejs ├── partials └── header.ejs ├── register.ejs ├── sample.ejs └── transactionsTable.ejs /.env.example: -------------------------------------------------------------------------------- 1 | CLIENT_ID= Your google signin client id 2 | JWT_SALT= Jwt salt used for authorization 3 | JWT_EXPDATE= Jwt expiry date in seconds 4 | FB_APP_ID= Facebook app id 5 | FB_APP_SECRET= Facebook app secret 6 | SITE_NAME= http://localhost:3000 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules 3 | Procfile -------------------------------------------------------------------------------- /Controllers/facebookSignInController.js: -------------------------------------------------------------------------------- 1 | const { 2 | getUserByEmail, 3 | create 4 | } = require("../Models/user.service"); 5 | const { sign } = require("jsonwebtoken"); 6 | const axios = require('axios'); // for promise based https requests 7 | 8 | module.exports = { 9 | fbSignIn : function(req,res) { 10 | 11 | //options for cookie 12 | let options = { 13 | expires: new Date(Date.now() + parseInt(process.env.JWT_EXPDATE)),//new Date(Date.now() + process.env.JWT_EXPDATE), 14 | secure: false, // set to true if your using https 15 | httpOnly: false, // The cookie only accessible by the web server 16 | // signed: true // Indicates if the cookie should be signed 17 | } 18 | 19 | const body = req.body; 20 | const token_to_inspect = body.accessToken; 21 | const dataObject = body.dataObject; // has email name and userId 22 | const returnObj = { 23 | success : 0, 24 | message : "Facebook Signin Failed" 25 | }; 26 | const extractData = { 27 | email : dataObject.email, 28 | password : null, 29 | first_name : null, 30 | last_name : null, 31 | phone_no : null, 32 | signin_type : 2 // signin type : 0 -> regular , 1 -> google , 2 -> facebook 33 | }; 34 | 35 | const fullName = dataObject.name.split(' '); 36 | extractData.first_name = fullName[0]; 37 | extractData.last_name = fullName[1]; 38 | 39 | //link to fetch our app token 40 | const getAppToken = 'https://graph.facebook.com/oauth/access_token' + '?client_id=' + process.env.FB_APP_ID + '&client_secret=' + process.env.FB_APP_SECRET + '&grant_type=client_credentials'; 41 | 42 | axios.get(getAppToken) 43 | .then((response) => { 44 | // response has our app token 45 | return Promise.resolve(response.data.access_token); 46 | }) 47 | .then((access_token) => { 48 | const url = 'https://graph.facebook.com/debug_token?' + 'input_token=' + token_to_inspect + '&access_token=' + access_token; 49 | return axios.get(url); 50 | }) 51 | .then((result)=>{ 52 | 53 | if( result.data.data.is_valid === true) { 54 | return Promise.resolve(); 55 | } else { 56 | return Promise.reject("Error, input token is invalid"); 57 | } 58 | 59 | }) 60 | .then(() => { 61 | return getUserByEmail(extractData.email); 62 | }) 63 | .then((result)=>{ 64 | 65 | if(result.length === 0) { //checking if user exists 66 | return create(extractData); 67 | } else { 68 | return "1"; 69 | } 70 | }) 71 | .then((result)=>{ 72 | if(result.length){ 73 | const jsontoken = sign({ resultdata: extractData }, process.env.JWT_SALT, { 74 | expiresIn: process.env.JWT_EXPDATE 75 | }); 76 | res.cookie('grishmat', jsontoken,options); // options is optional 77 | returnObj.success = 1; 78 | returnObj.message = "User logged in by Facebook sign In"; 79 | } 80 | res.json(returnObj); 81 | }) 82 | .catch((error) => { 83 | console.log("Error in verifying facebook tokens using api"); 84 | res.json(returnObj); 85 | //console.log(error); 86 | }); 87 | 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /Controllers/googleSignInController.js: -------------------------------------------------------------------------------- 1 | const { 2 | getUserByEmail, 3 | create 4 | } = require("../Models/user.service"); 5 | const { sign } = require("jsonwebtoken"); 6 | 7 | async function verify(extractData,id_token,client_id) { 8 | const {OAuth2Client} = require('google-auth-library'); // used to verify integrity of id token 9 | const client = new OAuth2Client(process.env.CLIENT_ID); 10 | 11 | const ticket = await client.verifyIdToken({ 12 | idToken: id_token, 13 | audience: client_id // Specify the client_id of the app(frontend) that accesses the backend 14 | }); 15 | const payload = ticket.getPayload(); // all data of user can also be verified using https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123 16 | const userid = payload['sub']; // userid (unique for every user), not using this for now 17 | extractData.email = payload['email']; 18 | extractData.first_name = payload['given_name']; 19 | extractData.last_name = payload['family_name']; 20 | } 21 | 22 | module.exports = { 23 | googleSignIn : function(req,res) { 24 | 25 | //options for cookie 26 | let options = { 27 | expires: new Date(Date.now() + parseInt(process.env.JWT_EXPDATE)),//new Date(Date.now() + process.env.JWT_EXPDATE), 28 | secure: false, // set to true if your using https 29 | httpOnly: false, // The cookie only accessible by the web server 30 | // signed: true // Indicates if the cookie should be signed 31 | } 32 | 33 | const body = req.body; 34 | var id_token = body.id_token; 35 | var client_id = body.client_id; 36 | var extractData = { 37 | email : null, 38 | password : null, 39 | first_name : null, 40 | last_name : null, 41 | phone_no : null, 42 | signin_type : 1 // signin type : 0 -> regular , 1 -> google , 2 -> facebook 43 | } 44 | 45 | var returnObj = { 46 | success : 0, 47 | message : "There was a problem" 48 | } 49 | 50 | verify(extractData,id_token,client_id) 51 | .then((result) => { 52 | return getUserByEmail(extractData.email); 53 | }) 54 | .then((result)=>{ 55 | if(result.length === 0) { //checking if user exists, if not then length of result will be zero. 56 | return create(extractData); 57 | } else { 58 | return "1"; 59 | } 60 | }) 61 | .then((result)=>{ 62 | if(result.length){ 63 | const jsontoken = sign({ resultdata: extractData }, process.env.JWT_SALT, { 64 | expiresIn: process.env.JWT_EXPDATE 65 | }); 66 | res.cookie('grishmat', jsontoken, options); // options is optional 67 | returnObj.token = jsontoken; 68 | returnObj.success = 1; 69 | returnObj.message = "User logged in by Google sign In"; 70 | } 71 | return res.json(returnObj); 72 | }) 73 | .catch((error)=>{ 74 | console.log("There was an error " + error); 75 | returnObj.success = 0; 76 | returnObj.message = "There was a problem"; 77 | return res.json(returnObj); 78 | }); 79 | }, 80 | } -------------------------------------------------------------------------------- /Controllers/userLoginController.js: -------------------------------------------------------------------------------- 1 | /* 2 | Handles the logic when user logs in 3 | */ 4 | 5 | const { 6 | getUserByEmail, 7 | } = require("../Models/user.service"); 8 | const { compareSync } = require('bcryptjs'); // for hashing password before storing in db 9 | const { sign } = require("jsonwebtoken"); 10 | 11 | module.exports = { 12 | login : function(req,res){ 13 | 14 | //options for cookie 15 | let options = { 16 | expires: new Date(Date.now() + parseInt(process.env.JWT_EXPDATE)),//new Date(Date.now() + process.env.JWT_EXPDATE), 17 | secure: false, // set to true if your using https 18 | httpOnly: false, // The cookie only accessible by the web server 19 | // signed: true // Indicates if the cookie should be signed 20 | } 21 | 22 | const body = req.body; 23 | console.log("User trying to login via normal login" + body.email + " " + body.password); 24 | 25 | getUserByEmail(body.email) 26 | .then((result)=>{ 27 | if(result.length === 0 || result[0].password==null){ 28 | 29 | res.json({ 30 | success: 0, 31 | message: "User doesn't exist" 32 | }); 33 | 34 | } else if (compareSync(body.password, result[0].password)) { //compareSync returns a boolean 35 | 36 | const jsontoken = sign({ resultdata: result[0] }, process.env.JWT_SALT , { 37 | expiresIn: process.env.JWT_EXPDATE 38 | }); 39 | res.cookie('grishmat', jsontoken, options); // options is optional 40 | res.json({ 41 | success: 1, 42 | message: "login successful", 43 | token: jsontoken 44 | }); 45 | 46 | } else { 47 | res.json({ 48 | success: 0, 49 | message: "invalid email or password" 50 | }); 51 | } 52 | 53 | }) 54 | .catch((err)=>{ 55 | console.log(err); 56 | res.json({ 57 | success: 0, 58 | message: "Login Failed" 59 | }); 60 | }); 61 | 62 | }, 63 | } -------------------------------------------------------------------------------- /Controllers/userOnHomepageController.js: -------------------------------------------------------------------------------- 1 | /* 2 | Displays name of user when user logs in 3 | */ 4 | 5 | module.exports = { 6 | onHome : function(req,res) { 7 | 8 | if(req.decode) { 9 | 10 | const first_name = req.decode.resultdata.first_name; // .decode object is attached after validating the jwt token 11 | const last_name = req.decode.resultdata.last_name; 12 | const signin_type = req.decode.resultdata.signin_type; 13 | const login_method = ['Form Sign In','Google Sign In','Facebook Sign In']; 14 | const str = "Logged In as " + first_name + " " + last_name + " via " + login_method[signin_type]; 15 | console.log(str); 16 | res.render('home',{name: str }); 17 | } else { 18 | res.render('home',{name:'You are not logged in'}); 19 | } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Controllers/userRegisterController.js: -------------------------------------------------------------------------------- 1 | const { 2 | getUserByEmail, 3 | create 4 | } = require("../Models/user.service"); 5 | const { genSaltSync, hashSync } = require('bcryptjs'); 6 | 7 | module.exports = { 8 | 9 | createUser: function(req,res) { 10 | const body = req.body; 11 | const salt = genSaltSync(10); 12 | body.password = hashSync(body.password, salt); //encrypting password before storing in dp 13 | 14 | var returnObj = { 15 | success : 0, 16 | message : "There was a problem" 17 | } 18 | 19 | getUserByEmail(body.email) // first check if user already exists 20 | .then((result)=>{ 21 | 22 | // result is an array 23 | if(result.length > 0){ 24 | returnObj.success = 0; 25 | returnObj.message = "User already exists"; 26 | return Promise.resolve(); 27 | } 28 | else { // array is empty in case user doesn't exist, so create user 29 | return create(body) 30 | } 31 | }) 32 | .then((result)=>{ 33 | 34 | if(result){ 35 | returnObj.success = 1; 36 | returnObj.message = "Registered successfully, you can login now"; 37 | } 38 | return res.json(returnObj); 39 | }) 40 | .catch((error)=>{ 41 | console.log("There was an error in sign up : " + error); 42 | returnObj.success = 0; 43 | returnObj.message = "There was a problem"; 44 | return res.json(returnObj); 45 | }); 46 | } 47 | } -------------------------------------------------------------------------------- /Controllers/userTransactionsController.js: -------------------------------------------------------------------------------- 1 | const { 2 | getUserByEmail, 3 | addPayment, 4 | getTransactionDetails 5 | } = require("../Models/user.service"); 6 | 7 | module.exports = { 8 | 9 | // adds payment details to database 10 | addPayment : function(req,res) { 11 | 12 | if(req.message) { 13 | res.json({ 14 | success : 0, 15 | message : req.message 16 | }); 17 | return; 18 | } 19 | 20 | var email = req.decode.resultdata.email; 21 | var data = req.body; 22 | getUserByEmail(email). 23 | then((result) => { 24 | data.uid = result[0].uid; 25 | var currentdate = new Date(); 26 | var tdate_ = currentdate.getDate() + "/"+ (currentdate.getMonth()+1) + "/" + currentdate.getFullYear() ; 27 | var ttime_ = currentdate.getHours() + ":" + currentdate.getMinutes() + ":" + currentdate.getSeconds(); 28 | data.tdate = tdate_; 29 | data.ttime = ttime_; 30 | return addPayment(data); 31 | }) 32 | .then((result)=>{ 33 | res.json({ 34 | success : 1, 35 | message : "Payment was successful" 36 | }) 37 | }) 38 | .catch((err) => { 39 | console.log("Error while registering transaction : "+err); 40 | res.json({ 41 | success : 0, 42 | message : "Couldn't process transaction" 43 | }); 44 | }); 45 | 46 | }, 47 | 48 | getTransactions : function(req,res) { 49 | 50 | if(req.message) { 51 | res.json({ 52 | success : 0, 53 | message : req.message 54 | }); 55 | return; 56 | } 57 | 58 | const email = req.decode.resultdata.email; 59 | getUserByEmail(email) 60 | .then((result)=>{ 61 | if(result) { 62 | return getTransactionDetails(result[0].uid); 63 | } else { 64 | reject("User does not exist in database"); 65 | } 66 | }) 67 | .then((result)=>{ 68 | 69 | // result is an array of objects 70 | res.render('transactionsTable',{resultArr:result}); 71 | /* 72 | res.json({ 73 | success : 1, 74 | message : "Fetch successful", 75 | data : result 76 | }); 77 | */ 78 | }) 79 | .catch((err)=>{ 80 | console.log("Error " + err); 81 | 82 | res.json({ 83 | success : 0, 84 | message : "There was a problem", 85 | data : null 86 | }); 87 | 88 | }); 89 | } 90 | } -------------------------------------------------------------------------------- /Models/db/fadb.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dumbbellcode/Full-Auth/bf09b5b95695dc084bfdfaa2a7aaa0bd58a1698d/Models/db/fadb.db -------------------------------------------------------------------------------- /Models/user.service.js: -------------------------------------------------------------------------------- 1 | //jshint esversion:6 2 | const sqlite3 = require('sqlite3').verbose(); 3 | const path = require('path') 4 | const dbpath = path.join(__dirname, '/db/fadb.db') 5 | module.exports = { 6 | create : function(data) { 7 | const myPromise = new Promise((resolve,reject)=>{ 8 | let db = new sqlite3.Database(dbpath); 9 | db.run( 10 | 'insert into registration(email,password,first_name,last_name,phone_no,signin_type) values (?,?,?,?,?,?)', 11 | [ 12 | data.email, 13 | data.password, 14 | data.first_name, 15 | data.last_name, 16 | data.phone_no, 17 | data.signin_type 18 | ] 19 | , 20 | function(error){ 21 | if (error) { 22 | reject(error); 23 | db.close(); 24 | return; 25 | } 26 | resolve(`A row has been inserted with rowid ${this.lastID}`); 27 | db.close(); 28 | } 29 | 30 | ); // query 31 | }); 32 | return myPromise; 33 | }, 34 | 35 | getUserById : function(userid) { 36 | const myPromise = new Promise((resolve,reject)=>{ 37 | let db = new sqlite3.Database(dbpath); 38 | db.all( 39 | 'select * from registration where uid=?', 40 | [userid], 41 | function(error,rows) { 42 | if (error) { 43 | reject(error); 44 | db.close(); 45 | return; 46 | } 47 | resolve(rows); 48 | db.close(); 49 | } 50 | ); //query 51 | }); 52 | return myPromise; 53 | }, 54 | 55 | getUserByEmail : function(email) { 56 | 57 | const myPromise = new Promise((resolve, reject)=>{ 58 | let db = new sqlite3.Database(dbpath); 59 | db.all( 60 | 'select * from registration where email=?', 61 | [email], 62 | function(error,rows) { 63 | if (error) { 64 | reject(error); 65 | db.close(); 66 | return; 67 | } 68 | resolve(rows); 69 | db.close(); 70 | } 71 | ); //query 72 | }); 73 | 74 | return myPromise; 75 | }, 76 | 77 | getUsers : function() { 78 | const myPromise = new Promise((resolve, reject)=>{ 79 | let db = new sqlite3.Database(dbpath); 80 | db.all( 81 | 'select * from registration', 82 | [], 83 | function(error,rows) { 84 | if (error) { 85 | reject(error); 86 | db.close(); 87 | return; 88 | } 89 | db.close(); 90 | resolve(rows); 91 | } 92 | ); //query 93 | }); 94 | return myPromise; 95 | }, 96 | 97 | updateUser : function(data) { 98 | const myPromise = new Promise((resolve, reject)=>{ 99 | let db = new sqlite3.Database(dbpath); 100 | db.run( 101 | 'update registration set password=?,first_name=?,last_name=?,phone_no=? where email=?', 102 | [ 103 | data.password, 104 | data.first_name, 105 | data.last_name, 106 | data.phone_no, 107 | data.email 108 | ] 109 | , 110 | function(error) { 111 | if (error) { 112 | reject(error); 113 | db.close(); 114 | return; 115 | } 116 | resolve(`Row(s) updated: ${this.changes}`); 117 | db.close(); 118 | } 119 | ); //query 120 | }); 121 | return myPromise 122 | }, 123 | 124 | addPayment : function(data) { 125 | 126 | const myPromise = new Promise((resolve,reject)=>{ 127 | let db = new sqlite3.Database(dbpath); 128 | db.run( 129 | 'insert into transactions(uid,pname,pid,pprice,tdate,ttime) values(?,?,?,?,?,?)', 130 | [ 131 | data.uid, 132 | data.product_name, 133 | data.product_id, 134 | data.product_price, 135 | data.tdate, 136 | data.ttime 137 | ] 138 | , 139 | function(error) { 140 | if (error) { 141 | reject(error); 142 | db.close(); 143 | return; 144 | } 145 | resolve(`A row has been inserted in transactions table with rowid ${this.lastID}`); 146 | db.close(); 147 | } 148 | ); //query 149 | }); 150 | 151 | return myPromise; 152 | }, 153 | 154 | getTransactionDetails : function(uid) { //get Transaction Details 155 | const myPromise = new Promise((resolve,reject)=>{ 156 | let db = new sqlite3.Database(dbpath); 157 | db.all( 158 | 'select * from transactions where uid=?', 159 | [uid] 160 | , 161 | function(error,rows) { 162 | if (error) { 163 | reject(error); 164 | db.close(); 165 | return; 166 | } 167 | resolve(rows); 168 | db.close(); 169 | } 170 | ); // query 171 | }); 172 | 173 | return myPromise; 174 | } 175 | } 176 | 177 | /* 178 | Below is npm mysql implementation 179 | 180 | const pool = require("../config/database"); 181 | 182 | module.exports = { 183 | 184 | create : function(data) { 185 | const myPromise = new Promise((resolve,reject)=>{ 186 | pool.query( 187 | 'insert into registration(email,password,first_name,last_name,phone_no,signin_type) values(?,?,?,?,?,?)', 188 | [ 189 | data.email, 190 | data.password, 191 | data.first_name, 192 | data.last_name, 193 | data.phone_no, 194 | data.signin_type 195 | ] 196 | , 197 | function(error,result,fields){ 198 | if (error) { 199 | reject(error); 200 | return; 201 | } 202 | resolve(result); 203 | } 204 | 205 | ); // query 206 | }); 207 | return myPromise; 208 | }, 209 | 210 | getUserById : function(userid) { 211 | const myPromise = new Promise((resolve,reject)=>{ 212 | pool.query( 213 | 'select * from registration where uid=?', 214 | [userid], 215 | function(error,result,fields) { 216 | if (error) { 217 | reject(error); 218 | return; 219 | } 220 | resolve(result); 221 | } 222 | ); //query 223 | }); 224 | return myPromise; 225 | }, 226 | 227 | getUserByEmail : function(email) { 228 | 229 | const myPromise = new Promise((resolve, reject)=>{ 230 | pool.query( 231 | 'select * from registration where email=?', 232 | [email], 233 | function(error,result,fields) { 234 | if (error) { 235 | reject(error); 236 | return; 237 | } 238 | resolve(result); 239 | } 240 | ); //query 241 | }); 242 | 243 | return myPromise; 244 | }, 245 | 246 | getUsers : function(callback) { 247 | pool.query( 248 | 'select * from registration', 249 | [], 250 | function(error,result,fields) { 251 | if(error) { 252 | return callback(error,null); 253 | } 254 | return callback(null,result) 255 | } 256 | );//query 257 | }, 258 | 259 | updateUser : function(data,callback) { 260 | pool.query( 261 | 'update registration set password=?,first_name=?,last_name=?,phone_no=? where email=?', 262 | [ 263 | data.password, 264 | data.first_name, 265 | data.last_name, 266 | data.phone_no, 267 | data.email 268 | ] 269 | , 270 | function(error,result,fields){ 271 | if(error) { 272 | return callback(error,null); 273 | } 274 | return callback(null,result) 275 | } 276 | 277 | ); // query 278 | }, 279 | 280 | addPayment : function(data) { 281 | 282 | const myPromise = new Promise((resolve,reject)=>{ 283 | pool.query( 284 | 'insert into transactions(uid,pname,pid,pprice,tdate,ttime) values(?,?,?,?,?,?)', 285 | [ 286 | data.uid, 287 | data.product_name, 288 | data.product_id, 289 | data.product_price, 290 | data.tdate, 291 | data.ttime 292 | ] 293 | , 294 | function(error,result,fields) { 295 | if (error) { 296 | reject(error); 297 | return; 298 | } 299 | resolve(result); 300 | } 301 | ); // query 302 | }); 303 | 304 | return myPromise; 305 | }, 306 | 307 | getTransactionDetails : function(uid) { //get Transaction Details 308 | const myPromise = new Promise((resolve,reject)=>{ 309 | pool.query( 310 | 'select * from transactions where uid=?', 311 | [uid] 312 | , 313 | function(error,result,fields) { 314 | if (error) { 315 | reject(error); 316 | return; 317 | } 318 | resolve(result); 319 | } 320 | ); // query 321 | }); 322 | 323 | return myPromise; 324 | } 325 | } 326 | 327 | */ -------------------------------------------------------------------------------- /Public/fbSignIn.js: -------------------------------------------------------------------------------- 1 | //const { get } = require("https"); 2 | 3 | window.fbAsyncInit = function() { 4 | FB.init({ 5 | appId : fb_app_id_ , /* fb_app_id_ is set in header */ 6 | cookie : true, 7 | xfbml : true, 8 | version : 'v8.0' 9 | }); 10 | 11 | FB.AppEvents.logPageView(); 12 | 13 | fbLoginStatus(); // automatic login try; 14 | 15 | $("#fbsignin").bind("click",()=>{ 16 | fbLogin(); 17 | }); 18 | 19 | }; 20 | 21 | (function(d, s, id){ 22 | var js, fjs = d.getElementsByTagName(s)[0]; 23 | if (d.getElementById(id)) {return;} 24 | js = d.createElement(s); js.id = id; 25 | js.src = "https://connect.facebook.net/en_US/sdk.js"; 26 | 27 | fjs.parentNode.insertBefore(js, fjs); 28 | }(document, 'script', 'facebook-jssdk')) 29 | 30 | /* 31 | function testAPI() { // Testing Graph API after login. See statusChangeCallback() for when this call is made. 32 | console.log('Welcome! Fetching your information.... '); 33 | FB.api('/me', function(response) { 34 | console.log('Successful login for: ' + response.name); 35 | console.log(response.id); 36 | getUserInfo(response.id); 37 | }); 38 | } 39 | */ 40 | 41 | function fbLogin() { 42 | 43 | FB.login(function(response) { 44 | //console.log(response); 45 | if (response.status === 'connected') { 46 | const userID = response.authResponse.userID; 47 | const accessToken = response.authResponse.accessToken; 48 | getUserInfo(userID,accessToken); 49 | } else { 50 | console.log("User couldn't log in to facebook"); 51 | } 52 | }, {scope: 'public_profile,email'}); 53 | } 54 | 55 | function getUserInfo(userId,accessToken) { 56 | FB.api( 57 | '/'+userId+'/?fields=id,name,email', 58 | 'GET', 59 | {}, 60 | function(response) { 61 | 62 | //response is an object with id, name and email, passing this as dataObject 63 | console.log(response); 64 | $.ajax({ 65 | url: SITE_NAME + '/api/fbsignin', // notice the s 66 | type: 'post', 67 | data: JSON.stringify({ 68 | accessToken : accessToken , 69 | dataObject : response 70 | }), 71 | contentType: "application/json", 72 | dataType: 'json', 73 | success: function(json) { 74 | if(json.success === 1) 75 | { 76 | $("#fbsignin span").html(" Signed In"); 77 | } 78 | console.log(json.message); 79 | window.location.replace(SITE_NAME); 80 | } 81 | }); 82 | } 83 | ); 84 | }; 85 | 86 | // not using as of now 87 | 88 | function statusChangeCallback(response) { // Called with the results from FB.getLoginStatus(). 89 | console.log('statusChangeCallback'); 90 | //console.log(response); // The current login status of the person. 91 | if (response.status === 'connected') { // Logged into your webpage and Facebook. 92 | getUserInfo(response.authResponse.userID,response.authResponse.accessToken); 93 | } else { // Not logged into your webpage or we are unable to tell. 94 | console.log("User isn't signined in"); 95 | } 96 | } 97 | 98 | 99 | function fbLoginStatus() { 100 | FB.getLoginStatus(function(response) { 101 | if (response.status === 'connected') { // Logged into your webpage and Facebook. 102 | statusChangeCallback(response); 103 | } 104 | }); 105 | } 106 | 107 | function fbLogout() { 108 | FB.logout(function(response) { 109 | console.log("Logged out of facebook") 110 | }); 111 | } 112 | /* 113 | On login -> fbLoginStatus -> statusChangecallback -> getUserinfo 114 | On click -> fbLogin -> getUserInfo 115 | */ -------------------------------------------------------------------------------- /Public/googleSignIn.js: -------------------------------------------------------------------------------- 1 | 2 | // client_id_ is put in header.ejs 3 | 4 | function onSuccess(googleUser) { 5 | var id_token_ = googleUser.getAuthResponse().id_token; 6 | var profile = googleUser.getBasicProfile(); 7 | /* 8 | console.log('ID: ' + profile.getId()); 9 | console.log('Full Name: ' + profile.getName()); 10 | console.log('Given Name: ' + profile.getGivenName()); 11 | console.log('Family Name: ' + profile.getFamilyName()); 12 | console.log('Image URL: ' + profile.getImageUrl()); 13 | console.log('Email: ' + profile.getEmail()); 14 | */ 15 | googleUser = {}; 16 | $.ajax({ 17 | url: SITE_NAME + '/api/gsignin', 18 | type: 'post', 19 | data: JSON.stringify({ 20 | id_token : id_token_ , 21 | client_id : client_id_ 22 | }), 23 | contentType: "application/json", 24 | dataType: 'json', 25 | success: function(json) { 26 | console.log(json.message); 27 | window.location.replace(SITE_NAME); 28 | } 29 | }); 30 | } 31 | function onFailure(error) { 32 | console.log(error); 33 | } 34 | function renderButton() { 35 | gapi.signin2.render('my-signin2', { 36 | 'scope': 'profile email', 37 | 'width': 180, 38 | 'height': 35, 39 | 'longtitle': true, 40 | 'theme': 'dark', 41 | 'onsuccess': onSuccess, 42 | 'onfailure': onFailure 43 | }); 44 | } 45 | function signOut() 46 | { 47 | 48 | var auth2 = gapi.auth2.getAuthInstance(); 49 | auth2.signOut().then(function () { 50 | console.log('User signed out of google.'); 51 | }); 52 | } 53 | -------------------------------------------------------------------------------- /Public/home.js: -------------------------------------------------------------------------------- 1 | 2 | // client_id_ in header.ejs 3 | function init() { 4 | window.gapi.load('auth2', function() { 5 | /* Ready. Make a call to gapi.auth2.init or some other API */ 6 | gapi.auth2.init({ 7 | client_id: client_id_ 8 | }) 9 | }); 10 | } 11 | 12 | function signOut() 13 | { 14 | var auth2 = gapi.auth2.getAuthInstance(); 15 | auth2.signOut().then(function () { 16 | console.log('User signed out of google.'); 17 | 18 | if (screen.width <= 699) { 19 | document.location = SITE_NAME; 20 | } else { 21 | window.location.replace(SITE_NAME); 22 | } 23 | }); 24 | } 25 | 26 | // FB sign out 27 | window.fbAsyncInit = function() { 28 | FB.init({ 29 | appId : fb_app_id_, /* Fb app id is already on top */ 30 | cookie : true, 31 | xfbml : true, 32 | version : 'v8.0' 33 | }); 34 | 35 | FB.AppEvents.logPageView(); 36 | FB.getLoginStatus(function(response) { 37 | if (response.status === 'connected') { // Logged into your webpage and Facebook. 38 | console.log(response); 39 | } 40 | }); 41 | 42 | }; 43 | 44 | (function(d, s, id){ 45 | var js, fjs = d.getElementsByTagName(s)[0]; 46 | if (d.getElementById(id)) {return;} 47 | js = d.createElement(s); js.id = id; 48 | js.src = "https://connect.facebook.net/en_US/sdk.js"; 49 | 50 | fjs.parentNode.insertBefore(js, fjs); 51 | }(document, 'script', 'facebook-jssdk')) 52 | 53 | function fbLogout() { 54 | FB.logout(function(response) { 55 | console.log("Logged out of facebook") 56 | if (screen.width <= 699) { 57 | document.location = SITE_NAME; 58 | } else { 59 | window.location.replace(SITE_NAME); 60 | } 61 | }); 62 | } 63 | 64 | function getCookie(name) { 65 | let cookie = {}; 66 | document.cookie.split(';').forEach(function(el) { 67 | let [k,v] = el.split('='); 68 | cookie[k.trim()] = v; 69 | }) 70 | //console.log("I got it " + cookie[name]); 71 | return cookie[name]; 72 | } 73 | 74 | $('#postpay').click(function(){ 75 | 76 | if( $('#product_name').val() === "" || $('#product_id').val() === "" || $('#product_price').val() === "" ) { 77 | console.log(" All fields are required "); 78 | return; 79 | } 80 | var x = getCookie('grishmat'); 81 | $.ajax({ 82 | url: SITE_NAME + '/api/pay', 83 | type: 'post', 84 | data : JSON.stringify({ 85 | product_name : $('#product_name').val(), 86 | product_id : $('#product_id').val(), 87 | product_price : $('#product_price').val() 88 | }), 89 | contentType: "application/json", 90 | dataType: 'json', 91 | xhrFields: { //setting this is very important as cookies won't be send otherwise 92 | withCredentials: true 93 | }, 94 | success : function(json) { 95 | const str = "
" + json.message + "
";
 96 |             $('#postpaymsg').hide().html(str).fadeIn(1000).delay(1000).fadeOut(2000) ;
 97 |             //console.log(json); 
 98 |         }  
 99 |     });
100 | }); 
101 | $('#getpay').click(function(){  //get history
102 |     var x = getCookie('grishmat'); 
103 |     if(x == undefined || x==null) return; 
104 |     $('#getpay i').css({"color":"LawnGreen"});
105 |     $("#details").load( `${SITE_NAME}/api/pay`);
106 |     $('#getpay').css({"margin-bottom":"5px"});
107 | });
108 | 
109 | $('#logout').click(function(){  //logs you out 
110 |     
111 |     //clears cookie 
112 |     var expdate = new Date()
113 |     expdate.setDate(expdate.getDate() - 1);
114 |     document.cookie = "grishmat=" + ";expires=" + expdate.toUTCString() + ";"; //grishmat is jwt token 
115 |     
116 |     fbLogout();
117 |     signOut();
118 |     // try {
119 |     //     signOut();  //signs out of google 
120 |     //     fbLogout(); //signs out of facebook
121 |     // } catch(err) {
122 |     //   console.log("All good "); 
123 |     // }
124 |     
125 |     //window.location.replace(SITE_NAME);
126 | });
127 | 
128 | 


--------------------------------------------------------------------------------
/Public/login.css:
--------------------------------------------------------------------------------
  1 | 
  2 | #logo{
  3 |     font-family: 'Roboto', sans-serif  !important;
  4 |     font-style: normal !important;
  5 |     background-color: #2B68AD;
  6 |     color: #007bff  !important; 
  7 |     text-align: center;
  8 |     font-size: 1.25rem;
  9 |     line-height: inherit;
 10 |     padding-bottom: 10px;
 11 | }
 12 | #logo a {
 13 |     margin: 0px; 
 14 | }
 15 | 
 16 | #logreg-forms{
 17 |     width:412px;
 18 |     margin:10vh auto;
 19 |     background-color:#f3f3f3;
 20 |     box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
 21 |     transition: all 0.3s cubic-bezier(.25,.8,.25,1);
 22 | }
 23 | 
 24 | #logreg-forms form {
 25 |     width: 100%;
 26 |     max-width: 410px;
 27 |     padding: 15px;
 28 |     margin: auto;
 29 | }
 30 | 
 31 | #logreg-forms .form-control {
 32 |     position: relative;
 33 |     box-sizing: border-box;
 34 |     height: auto;
 35 |     padding: 10px;
 36 |     font-size: 16px;
 37 | }
 38 | #logreg-forms .form-control:focus { z-index: 2; }
 39 | 
 40 | #logreg-forms .social-login{
 41 |     width:390px;
 42 |     margin:0 auto;
 43 |     margin-bottom: 14px; 
 44 |     text-align: center ;
 45 | }
 46 | #logreg-forms .social-btn{
 47 |     font-weight: 100;
 48 |     color:white;
 49 |     width:180px;
 50 |     font-size: 0.9rem;
 51 | }
 52 | 
 53 | #my-signin2,#my-signin2 div{
 54 |     display:inline-block;
 55 | }
 56 | 
 57 | 
 58 | #logreg-forms a{
 59 |     display: block;
 60 |     padding-top:10px;
 61 |     /* color:lightseagreen; */
 62 | }
 63 | 
 64 | #logreg-form .lines{
 65 |     width:200px;
 66 |     border:1px solid red;
 67 | }
 68 | 
 69 | 
 70 | #logreg-forms button[type="submit"]{ margin-top:10px; }
 71 | 
 72 | #logreg-forms .facebook-btn{  background-color:#3C589C; }
 73 | 
 74 | #logreg-forms .facebook-btn:hover{  box-shadow: 0 0 5px rgb(85, 182, 226);  }
 75 | 
 76 | #logreg-forms .form-reset { display: none; }
 77 | 
 78 | 
 79 | .form-signup .social-login{
 80 |     width:210px !important;
 81 |     margin: 0 auto;
 82 | }
 83 | 
 84 | input:invalid {
 85 |     background-color: #ffdddd;
 86 | }
 87 | 
 88 | .error {
 89 |     font-size : 0.7rem; 
 90 | }
 91 | 
 92 | /* Registration Page */
 93 | 
 94 | #first_name, #last_name {
 95 |     display: inline-block;
 96 |     width: 49.3%;
 97 | }
 98 | 
 99 | 
100 | 
101 | input {
102 |     margin-bottom : 10px; 
103 | }
104 | 
105 | /* Mobile */
106 | @media screen and (max-width:500px){
107 |     #logreg-forms{
108 |         width:300px;
109 |     }
110 |     
111 |     #logreg-forms  .social-login{
112 |         text-align: center;
113 |         width:200px;
114 |         margin:0 auto;
115 |         margin-bottom: 10px;
116 |     }
117 |     #logreg-forms  .social-btn{
118 |         margin:5px;
119 |         font-weight: 100;
120 |         color:white;
121 |         width:185px;
122 |         font-size: 0.9rem;
123 |     }
124 | 
125 |     #logreg-forms .social-btn:nth-child(1){
126 |         margin-bottom: 5px;
127 |     }
128 |     #logreg-forms .social-btn span{
129 |         display: none;
130 |     }
131 |     #logreg-forms  .facebook-btn:after{
132 |         content:'Facebook';
133 |     }
134 |     
135 | }
136 | 
137 | /* Mobile Register*/
138 | @media screen and (max-width:500px){ 
139 | #first_name, #last_name {
140 |     display : block;
141 |     width : 100%; 
142 | }
143 | }
144 | 


--------------------------------------------------------------------------------
/Public/login.js:
--------------------------------------------------------------------------------
 1 | var expdate = new Date();
 2 | expdate.setDate(expdate.getDate() + 7);
 3 | 
 4 | function validateForm() {
 5 | 
 6 |     var errorCount = 0; 
 7 |     var fields = ['email','password'];
 8 |     var a = $('#email').val(); 
 9 |     var b = $('#password').val(); 
10 |     fields.forEach((el)=> {
11 |         var x = $("#" + el).val(); 
12 |         if (x === null || x === "") {
13 |             $("#" + el + "_error").html("This field can't be empty");
14 |             $("#" + el).css({"margin-bottom":"0px"});
15 |             ++errorCount;
16 |         } else  {
17 |             $("#" + el + "_error").html("");
18 |             $("#" + el).css({"margin-bottom":"10px"});
19 |         }
20 |     });
21 | 
22 |     regex = /\S+@\S+\.\S+/;
23 |     if(a!=null && a.length!=0 && !regex.test(a)) {
24 |         $('#email_error').html("Please enter a valid email");
25 |         $("#email").css({"margin-bottom":"0px"});
26 |         ++errorCount;
27 |     } 
28 |     if(b!=null && b.length!=0 && b.length < 8) {
29 |         $('#password_error').html("Password is not valid");
30 |         $("#password").css({"margin-bottom":"0px"});
31 |         ++errorCount;
32 |     } 
33 |     if (errorCount) return 0;
34 |     return 1
35 | }
36 | 
37 | // logs in the user from nu 
38 | $("#main_login").bind("click", function(){
39 |     if(validateForm()) {
40 |         
41 |         $.ajax({
42 |             url: SITE_NAME + '/login',  
43 |             type: 'post',
44 |             data: JSON.stringify({ 
45 |               email: $('#email').val(),
46 |               password: $('#password').val(),
47 |             }),
48 |             contentType: "application/json",
49 |             dataType: 'json',
50 |             success: function(jsonobj) {        
51 |                 if(jsonobj.success===1) {   
52 |                     $('#login_message').html("Logged in successfully") ;     
53 |                     window.location.replace(SITE_NAME);
54 |                 } else {
55 |                     $('#login_message').html(jsonobj.message);
56 |                 }
57 |             }
58 |         }); 
59 |     }
60 |     
61 | });
62 | 
63 | 
64 | /*
65 | 
66 | // For reset password feature :( not using as of now 
67 | 
68 | function toggleResetPswd(e){
69 |     e.preventDefault();
70 |     $('#logreg-forms .form-signin').toggle() // display:block or none
71 |     $('#logreg-forms .form-reset').toggle() // display:block or none
72 | }
73 | 
74 | $(()=>{
75 |     // Login Register Form
76 |     $('#logreg-forms #forgot_pswd').click(toggleResetPswd);
77 |     $('#logreg-forms #cancel_reset').click(toggleResetPswd);
78 | })
79 | 
80 | */ 
81 | 


--------------------------------------------------------------------------------
/Public/register.js:
--------------------------------------------------------------------------------
 1 | var expdate = new Date();
 2 | expdate.setDate(expdate.getDate() + 7);
 3 | const loginPage = SITE_NAME + "/login";
 4 | 
 5 | function validateForm() {
 6 |     /*
 7 |     Damn this was hectic 
 8 |     */
 9 |     var errorCount = 0; 
10 |     var fields = ['first_name','last_name','email','password','confirm_password'];
11 |     var a = $('#email').val(); 
12 |     var b = $('#password').val(); 
13 |     var c = $('#confirm_password').val(); 
14 |     fields.forEach(function(el) {
15 |         var x = $("#" + el).val(); 
16 |         if (x === null || x === "") {
17 |             if(fields.indexOf(el) < 3) {
18 |                 $("#" + "email_error").html("Above field(s) can't be empty");
19 |                 $("#email").css({"margin-bottom":"0px"});
20 |             } else { 
21 |                 var s = '#' + el; 
22 |                 $("#" + el + "_error").html("This field can't be empty");
23 |                 $(s).css({"margin-bottom":"0px"}); 
24 |             }
25 |             ++errorCount;
26 |         }  else   { 
27 |             $("#" + el + "_error").html(""); 
28 |             $("#" + el).css({"margin-bottom":"10px"}); 
29 |         }
30 |     });
31 | 
32 |     regex = /\S+@\S+\.\S+/;
33 |     if(a!=null && a.length!=0 && !regex.test(a)) {
34 |         $('#email_error').html("Please enter a valid email");
35 |         $("#email").css({"margin-bottom":"0px"});
36 |         ++errorCount;
37 |     } 
38 |     if(b!=null && b.length!=0 && b.length < 8) {
39 |         $('#password_error').html("Password too small, should be atleast 8 characters long");
40 |         $("#password").css({"margin-bottom":"0px"});
41 |         ++errorCount;
42 |     } 
43 |     if(c.length>0 && b!=c) {
44 |         $('#confirm_password_error').html("Passwords don't match");
45 |         $("#confirm_password").css({"margin-bottom":"0px"});
46 |         ++errorCount;
47 |     } 
48 |     if (errorCount) return 0;
49 |     return 1
50 | }
51 | 
52 | /* Register */ 
53 | $("#main_register").bind("click", function(){ 
54 |     
55 |     var flag = validateForm();
56 |     console.log(flag); 
57 |     if(flag === 1)
58 |     {
59 |         $.ajax({
60 |             url: SITE_NAME + '/register',  
61 |             type: 'post',
62 |             data: JSON.stringify({ 
63 |               email: $('#email').val(),
64 |               password: $('#password').val(),
65 |               first_name: $('#first_name').val(),
66 |               last_name: $('#last_name').val(),
67 |               signin_type : 0 
68 |             }),
69 |             contentType: "application/json",
70 |             dataType: 'json',
71 |             success: function(jsonobj) {
72 |               console.log(jsonobj);         
73 |               if(jsonobj.success===1)
74 |               { 
75 |                   $('#register_error').html(jsonobj.message) ;     
76 |                   window.location.replace(loginPage);
77 |               } else {
78 |                 $('#register_error').html(jsonobj.message);
79 |               }
80 |             }
81 |         }); 
82 |     }
83 | }); 


--------------------------------------------------------------------------------
/Public/signOut.js:
--------------------------------------------------------------------------------
 1 | // signs out everything, makes life easy 
 2 | 
 3 | function realSignOut()
 4 | {
 5 |     fbLogout(); // inside fbSignin.js
 6 |     signOut();   // inside googleSignin.js
 7 |     var expdate = new Date()
 8 |     expdate.setDate(expdate.getDate() - 1);
 9 |     document.cookie = "grishmat=" + ";expires=" + expdate.toUTCString() + ";"; //grishmat is jwt token 
10 | 
11 |     console.log("Real Sign Out"); 
12 | }
13 | 


--------------------------------------------------------------------------------
/Routes/login.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |    Handles /api/login
 3 | */
 4 | 
 5 | var express = require('express');
 6 | const router = express.Router(); 
 7 | 
 8 | router.use(express.json());
 9 | 
10 | const {
11 |     login 
12 | } = require("../Controllers/userLoginController");
13 | 
14 | 
15 | router.get("/login", (req, res) => {
16 |     res.render('login',{}); 
17 | });  
18 | router.post("/login", login);
19 | 
20 | module.exports = router; 


--------------------------------------------------------------------------------
/Routes/oAuthSignIn.js:
--------------------------------------------------------------------------------
 1 | var express = require('express');
 2 | const router = express.Router(); 
 3 | 
 4 | router.use(express.json());
 5 | 
 6 | const {
 7 |     googleSignIn
 8 | } = require("../Controllers/googleSignInController");
 9 | 
10 | const {
11 |     fbSignIn
12 | } = require("../Controllers/facebookSignInController");
13 | 
14 | router.post("/gsignin", googleSignIn);  
15 | router.post("/fbsignin", fbSignIn);    
16 | 
17 | module.exports = router; 


--------------------------------------------------------------------------------
/Routes/onHome.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |     path : / 
 3 | */
 4 | 
 5 | const {
 6 |     onHome
 7 | } = require("../Controllers/userOnHomepageController");
 8 | 
 9 | const { checkToken } = require("../tokenauth/tokenvalidation");
10 | 
11 | var express = require('express');
12 | const router = express.Router(); 
13 | 
14 | router.use(express.json());
15 | 
16 | router.get("/",checkToken, onHome); 
17 | module.exports = router 
18 | 
19 | 


--------------------------------------------------------------------------------
/Routes/paymentRoutes.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |     Handles /api/pay
 3 | */
 4 | const { checkToken } = require("../tokenauth/tokenvalidation");
 5 | 
 6 | const {
 7 |     addPayment
 8 | } = require("../Controllers/userTransactionsController"); 
 9 | 
10 | const {
11 |     getTransactions
12 | } = require("../Controllers/userTransactionsController");
13 | 
14 | 
15 | var express = require('express');
16 | const router = express.Router(); 
17 | 
18 | router.use(express.json());
19 | 
20 | router.post("/pay",checkToken,addPayment); 
21 | router.get("/pay",checkToken,getTransactions); 
22 | 
23 | module.exports = router 


--------------------------------------------------------------------------------
/Routes/register.js:
--------------------------------------------------------------------------------
 1 | /*
 2 |     Handles /api/register 
 3 | */
 4 | 
 5 | var express = require('express');
 6 | const router = express.Router(); 
 7 | 
 8 | router.use(express.json());
 9 | 
10 | const {
11 |     createUser
12 | } = require("../Controllers/userRegisterController"); 
13 | 
14 | router.get("/register", (req, res) => {
15 |   res.render('register',{}); 
16 | });
17 | 
18 | router.post("/register",createUser); 
19 | 
20 | module.exports = router  


--------------------------------------------------------------------------------
/dbrunonce.js:
--------------------------------------------------------------------------------
 1 | 
 2 | const path = require('path')
 3 | const dbpath = path.join(__dirname, 'Models/db/fadb.db')
 4 | // database name fadb (meaning full auth db)
 5 | const sqlite3 = require('sqlite3').verbose();
 6 | let db = new sqlite3.Database(dbpath); //created if doesn't exist. 
 7 | db.run("CREATE TABLE IF NOT EXISTS registration ( uid  INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT, password TEXT, first_name TEXT, last_name TEXT, phone_no TEXT, signin_type INTEGER )");
 8 | db.run(" CREATE TABLE IF NOT EXISTS transactions ( uid TEXT, pname TEXT, pid TEXT, pprice TEXT, tdate TEXT, ttime TEXT ) ");
 9 | db.close();
10 | 
11 | /*
12 | CREATE TABLE IF NOT EXISTS registration (
13 |     uid  INTEGER PRIMARY KEY AUTOINCREMENT,
14 |     email TEXT,
15 |     password TEXT,
16 |     first_name TEXT,
17 |     last_name TEXT,
18 |     phone_no TEXT,
19 |     signin_type INTEGER
20 | );
21 | CREATE TABLE IF NOT EXISTS transactions (
22 |     uid TEXT,
23 |     pname TEXT,
24 |     pid TEXT,
25 |     pprice TEXT,
26 |     tdate TEXT,
27 |     ttime TEXT
28 | );
29 | INSERT INTO registration(email) VALUES ("assdsd");
30 | SELECT * FROM registration
31 | 
32 | */


--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
 1 | //jshint esversion:6
 2 | 
 3 | require('dotenv').config();
 4 | var express = require('express');
 5 | var app = express();
 6 | //var bodyParser = require('body-parser');
 7 | const https = require('https');
 8 | var cookieParser = require("cookie-parser");
 9 | 
10 | 
11 | app.use(cookieParser());
12 | // app.use(bodyParser.urlencoded({ extended: true }));
13 | app.use(express.static(__dirname + '/Public'));
14 | 
15 | app.set('views', __dirname + '/views');
16 | app.set('view engine', 'ejs'); 
17 | 
18 | const home = require("./Routes/onHome"); 
19 | const oAuthSignIn = require("./Routes/oAuthSignIn"); 
20 | const login = require("./Routes/login");
21 | const register = require("./Routes/register"); 
22 | const paymentRoutes = require("./Routes/paymentRoutes");
23 | 
24 | const fs = require('fs'); // for ssl certificate 
25 | 
26 | app.use("/", home);
27 | app.use("/",login); 
28 | app.use("/",register);
29 | 
30 | /* Requests from all buttons(except login/register) pass thorough path '/api' */ 
31 | app.use("/api",oAuthSignIn); 
32 | app.use("/api",paymentRoutes); 
33 | 
34 | app.listen(process.env.PORT || 3000,function(){
35 |   console.log("Server running on post 3000"); 
36 | });
37 | 
38 | 
39 | //postgresql-aerodynamic-23734


--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
   1 | {
   2 |   "name": "login-page",
   3 |   "version": "1.0.0",
   4 |   "lockfileVersion": 1,
   5 |   "requires": true,
   6 |   "dependencies": {
   7 |     "abbrev": {
   8 |       "version": "1.1.1",
   9 |       "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
  10 |       "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
  11 |     },
  12 |     "abort-controller": {
  13 |       "version": "3.0.0",
  14 |       "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
  15 |       "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
  16 |       "requires": {
  17 |         "event-target-shim": "^5.0.0"
  18 |       }
  19 |     },
  20 |     "accepts": {
  21 |       "version": "1.3.7",
  22 |       "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
  23 |       "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
  24 |       "requires": {
  25 |         "mime-types": "~2.1.24",
  26 |         "negotiator": "0.6.2"
  27 |       }
  28 |     },
  29 |     "agent-base": {
  30 |       "version": "6.0.1",
  31 |       "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz",
  32 |       "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==",
  33 |       "requires": {
  34 |         "debug": "4"
  35 |       },
  36 |       "dependencies": {
  37 |         "debug": {
  38 |           "version": "4.1.1",
  39 |           "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
  40 |           "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
  41 |           "requires": {
  42 |             "ms": "^2.1.1"
  43 |           }
  44 |         },
  45 |         "ms": {
  46 |           "version": "2.1.2",
  47 |           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
  48 |           "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
  49 |         }
  50 |       }
  51 |     },
  52 |     "ajv": {
  53 |       "version": "6.12.5",
  54 |       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz",
  55 |       "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==",
  56 |       "optional": true,
  57 |       "requires": {
  58 |         "fast-deep-equal": "^3.1.1",
  59 |         "fast-json-stable-stringify": "^2.0.0",
  60 |         "json-schema-traverse": "^0.4.1",
  61 |         "uri-js": "^4.2.2"
  62 |       }
  63 |     },
  64 |     "ansi-regex": {
  65 |       "version": "2.1.1",
  66 |       "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
  67 |       "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
  68 |     },
  69 |     "ansi-styles": {
  70 |       "version": "3.2.1",
  71 |       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
  72 |       "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
  73 |       "requires": {
  74 |         "color-convert": "^1.9.0"
  75 |       }
  76 |     },
  77 |     "aproba": {
  78 |       "version": "1.2.0",
  79 |       "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
  80 |       "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
  81 |     },
  82 |     "are-we-there-yet": {
  83 |       "version": "1.1.5",
  84 |       "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
  85 |       "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
  86 |       "requires": {
  87 |         "delegates": "^1.0.0",
  88 |         "readable-stream": "^2.0.6"
  89 |       }
  90 |     },
  91 |     "array-flatten": {
  92 |       "version": "1.1.1",
  93 |       "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
  94 |       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
  95 |     },
  96 |     "arrify": {
  97 |       "version": "2.0.1",
  98 |       "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
  99 |       "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="
 100 |     },
 101 |     "asn1": {
 102 |       "version": "0.2.4",
 103 |       "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
 104 |       "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
 105 |       "optional": true,
 106 |       "requires": {
 107 |         "safer-buffer": "~2.1.0"
 108 |       }
 109 |     },
 110 |     "assert-plus": {
 111 |       "version": "1.0.0",
 112 |       "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
 113 |       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
 114 |       "optional": true
 115 |     },
 116 |     "async": {
 117 |       "version": "0.9.2",
 118 |       "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
 119 |       "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
 120 |     },
 121 |     "asynckit": {
 122 |       "version": "0.4.0",
 123 |       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 124 |       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
 125 |       "optional": true
 126 |     },
 127 |     "aws-sign2": {
 128 |       "version": "0.7.0",
 129 |       "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
 130 |       "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
 131 |       "optional": true
 132 |     },
 133 |     "aws4": {
 134 |       "version": "1.10.1",
 135 |       "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz",
 136 |       "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
 137 |       "optional": true
 138 |     },
 139 |     "axios": {
 140 |       "version": "0.20.0",
 141 |       "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz",
 142 |       "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==",
 143 |       "requires": {
 144 |         "follow-redirects": "^1.10.0"
 145 |       }
 146 |     },
 147 |     "balanced-match": {
 148 |       "version": "1.0.0",
 149 |       "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
 150 |       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
 151 |     },
 152 |     "base64-js": {
 153 |       "version": "1.3.1",
 154 |       "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
 155 |       "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
 156 |     },
 157 |     "bcrypt-pbkdf": {
 158 |       "version": "1.0.2",
 159 |       "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
 160 |       "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
 161 |       "optional": true,
 162 |       "requires": {
 163 |         "tweetnacl": "^0.14.3"
 164 |       }
 165 |     },
 166 |     "bcryptjs": {
 167 |       "version": "2.4.3",
 168 |       "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
 169 |       "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms="
 170 |     },
 171 |     "bignumber.js": {
 172 |       "version": "9.0.0",
 173 |       "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
 174 |       "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
 175 |     },
 176 |     "block-stream": {
 177 |       "version": "0.0.9",
 178 |       "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
 179 |       "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
 180 |       "optional": true,
 181 |       "requires": {
 182 |         "inherits": "~2.0.0"
 183 |       }
 184 |     },
 185 |     "body-parser": {
 186 |       "version": "1.19.0",
 187 |       "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
 188 |       "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
 189 |       "requires": {
 190 |         "bytes": "3.1.0",
 191 |         "content-type": "~1.0.4",
 192 |         "debug": "2.6.9",
 193 |         "depd": "~1.1.2",
 194 |         "http-errors": "1.7.2",
 195 |         "iconv-lite": "0.4.24",
 196 |         "on-finished": "~2.3.0",
 197 |         "qs": "6.7.0",
 198 |         "raw-body": "2.4.0",
 199 |         "type-is": "~1.6.17"
 200 |       }
 201 |     },
 202 |     "brace-expansion": {
 203 |       "version": "1.1.11",
 204 |       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 205 |       "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
 206 |       "requires": {
 207 |         "balanced-match": "^1.0.0",
 208 |         "concat-map": "0.0.1"
 209 |       }
 210 |     },
 211 |     "buffer-equal-constant-time": {
 212 |       "version": "1.0.1",
 213 |       "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
 214 |       "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
 215 |     },
 216 |     "bytes": {
 217 |       "version": "3.1.0",
 218 |       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
 219 |       "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
 220 |     },
 221 |     "caseless": {
 222 |       "version": "0.12.0",
 223 |       "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
 224 |       "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
 225 |       "optional": true
 226 |     },
 227 |     "chalk": {
 228 |       "version": "2.4.2",
 229 |       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
 230 |       "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
 231 |       "requires": {
 232 |         "ansi-styles": "^3.2.1",
 233 |         "escape-string-regexp": "^1.0.5",
 234 |         "supports-color": "^5.3.0"
 235 |       }
 236 |     },
 237 |     "chownr": {
 238 |       "version": "1.1.4",
 239 |       "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
 240 |       "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
 241 |     },
 242 |     "code-point-at": {
 243 |       "version": "1.1.0",
 244 |       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
 245 |       "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
 246 |     },
 247 |     "color-convert": {
 248 |       "version": "1.9.3",
 249 |       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
 250 |       "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
 251 |       "requires": {
 252 |         "color-name": "1.1.3"
 253 |       }
 254 |     },
 255 |     "color-name": {
 256 |       "version": "1.1.3",
 257 |       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
 258 |       "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
 259 |     },
 260 |     "combined-stream": {
 261 |       "version": "1.0.8",
 262 |       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 263 |       "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
 264 |       "optional": true,
 265 |       "requires": {
 266 |         "delayed-stream": "~1.0.0"
 267 |       }
 268 |     },
 269 |     "concat-map": {
 270 |       "version": "0.0.1",
 271 |       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
 272 |       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
 273 |     },
 274 |     "console-control-strings": {
 275 |       "version": "1.1.0",
 276 |       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
 277 |       "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
 278 |     },
 279 |     "content-disposition": {
 280 |       "version": "0.5.3",
 281 |       "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
 282 |       "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
 283 |       "requires": {
 284 |         "safe-buffer": "5.1.2"
 285 |       }
 286 |     },
 287 |     "content-type": {
 288 |       "version": "1.0.4",
 289 |       "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
 290 |       "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
 291 |     },
 292 |     "cookie": {
 293 |       "version": "0.4.0",
 294 |       "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
 295 |       "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
 296 |     },
 297 |     "cookie-parser": {
 298 |       "version": "1.4.5",
 299 |       "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz",
 300 |       "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==",
 301 |       "requires": {
 302 |         "cookie": "0.4.0",
 303 |         "cookie-signature": "1.0.6"
 304 |       }
 305 |     },
 306 |     "cookie-signature": {
 307 |       "version": "1.0.6",
 308 |       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
 309 |       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
 310 |     },
 311 |     "core-util-is": {
 312 |       "version": "1.0.2",
 313 |       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
 314 |       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
 315 |     },
 316 |     "dashdash": {
 317 |       "version": "1.14.1",
 318 |       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
 319 |       "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
 320 |       "optional": true,
 321 |       "requires": {
 322 |         "assert-plus": "^1.0.0"
 323 |       }
 324 |     },
 325 |     "debug": {
 326 |       "version": "2.6.9",
 327 |       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
 328 |       "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
 329 |       "requires": {
 330 |         "ms": "2.0.0"
 331 |       }
 332 |     },
 333 |     "deep-extend": {
 334 |       "version": "0.6.0",
 335 |       "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
 336 |       "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
 337 |     },
 338 |     "delayed-stream": {
 339 |       "version": "1.0.0",
 340 |       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
 341 |       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
 342 |       "optional": true
 343 |     },
 344 |     "delegates": {
 345 |       "version": "1.0.0",
 346 |       "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
 347 |       "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
 348 |     },
 349 |     "depd": {
 350 |       "version": "1.1.2",
 351 |       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
 352 |       "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
 353 |     },
 354 |     "destroy": {
 355 |       "version": "1.0.4",
 356 |       "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
 357 |       "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
 358 |     },
 359 |     "detect-libc": {
 360 |       "version": "1.0.3",
 361 |       "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
 362 |       "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
 363 |     },
 364 |     "dotenv": {
 365 |       "version": "8.2.0",
 366 |       "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
 367 |       "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
 368 |     },
 369 |     "ecc-jsbn": {
 370 |       "version": "0.1.2",
 371 |       "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
 372 |       "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
 373 |       "optional": true,
 374 |       "requires": {
 375 |         "jsbn": "~0.1.0",
 376 |         "safer-buffer": "^2.1.0"
 377 |       }
 378 |     },
 379 |     "ecdsa-sig-formatter": {
 380 |       "version": "1.0.11",
 381 |       "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
 382 |       "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
 383 |       "requires": {
 384 |         "safe-buffer": "^5.0.1"
 385 |       }
 386 |     },
 387 |     "ee-first": {
 388 |       "version": "1.1.1",
 389 |       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
 390 |       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
 391 |     },
 392 |     "ejs": {
 393 |       "version": "3.1.5",
 394 |       "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz",
 395 |       "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==",
 396 |       "requires": {
 397 |         "jake": "^10.6.1"
 398 |       }
 399 |     },
 400 |     "encodeurl": {
 401 |       "version": "1.0.2",
 402 |       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
 403 |       "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
 404 |     },
 405 |     "escape-html": {
 406 |       "version": "1.0.3",
 407 |       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
 408 |       "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
 409 |     },
 410 |     "escape-string-regexp": {
 411 |       "version": "1.0.5",
 412 |       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
 413 |       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
 414 |     },
 415 |     "etag": {
 416 |       "version": "1.8.1",
 417 |       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
 418 |       "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
 419 |     },
 420 |     "event-target-shim": {
 421 |       "version": "5.0.1",
 422 |       "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
 423 |       "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
 424 |     },
 425 |     "express": {
 426 |       "version": "4.17.1",
 427 |       "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
 428 |       "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
 429 |       "requires": {
 430 |         "accepts": "~1.3.7",
 431 |         "array-flatten": "1.1.1",
 432 |         "body-parser": "1.19.0",
 433 |         "content-disposition": "0.5.3",
 434 |         "content-type": "~1.0.4",
 435 |         "cookie": "0.4.0",
 436 |         "cookie-signature": "1.0.6",
 437 |         "debug": "2.6.9",
 438 |         "depd": "~1.1.2",
 439 |         "encodeurl": "~1.0.2",
 440 |         "escape-html": "~1.0.3",
 441 |         "etag": "~1.8.1",
 442 |         "finalhandler": "~1.1.2",
 443 |         "fresh": "0.5.2",
 444 |         "merge-descriptors": "1.0.1",
 445 |         "methods": "~1.1.2",
 446 |         "on-finished": "~2.3.0",
 447 |         "parseurl": "~1.3.3",
 448 |         "path-to-regexp": "0.1.7",
 449 |         "proxy-addr": "~2.0.5",
 450 |         "qs": "6.7.0",
 451 |         "range-parser": "~1.2.1",
 452 |         "safe-buffer": "5.1.2",
 453 |         "send": "0.17.1",
 454 |         "serve-static": "1.14.1",
 455 |         "setprototypeof": "1.1.1",
 456 |         "statuses": "~1.5.0",
 457 |         "type-is": "~1.6.18",
 458 |         "utils-merge": "1.0.1",
 459 |         "vary": "~1.1.2"
 460 |       }
 461 |     },
 462 |     "extend": {
 463 |       "version": "3.0.2",
 464 |       "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
 465 |       "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
 466 |     },
 467 |     "extsprintf": {
 468 |       "version": "1.3.0",
 469 |       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
 470 |       "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
 471 |       "optional": true
 472 |     },
 473 |     "fast-deep-equal": {
 474 |       "version": "3.1.3",
 475 |       "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
 476 |       "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
 477 |       "optional": true
 478 |     },
 479 |     "fast-json-stable-stringify": {
 480 |       "version": "2.1.0",
 481 |       "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
 482 |       "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
 483 |       "optional": true
 484 |     },
 485 |     "fast-text-encoding": {
 486 |       "version": "1.0.3",
 487 |       "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz",
 488 |       "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig=="
 489 |     },
 490 |     "filelist": {
 491 |       "version": "1.0.1",
 492 |       "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz",
 493 |       "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==",
 494 |       "requires": {
 495 |         "minimatch": "^3.0.4"
 496 |       }
 497 |     },
 498 |     "finalhandler": {
 499 |       "version": "1.1.2",
 500 |       "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
 501 |       "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
 502 |       "requires": {
 503 |         "debug": "2.6.9",
 504 |         "encodeurl": "~1.0.2",
 505 |         "escape-html": "~1.0.3",
 506 |         "on-finished": "~2.3.0",
 507 |         "parseurl": "~1.3.3",
 508 |         "statuses": "~1.5.0",
 509 |         "unpipe": "~1.0.0"
 510 |       }
 511 |     },
 512 |     "follow-redirects": {
 513 |       "version": "1.13.0",
 514 |       "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz",
 515 |       "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA=="
 516 |     },
 517 |     "forever-agent": {
 518 |       "version": "0.6.1",
 519 |       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
 520 |       "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
 521 |       "optional": true
 522 |     },
 523 |     "form-data": {
 524 |       "version": "2.3.3",
 525 |       "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
 526 |       "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
 527 |       "optional": true,
 528 |       "requires": {
 529 |         "asynckit": "^0.4.0",
 530 |         "combined-stream": "^1.0.6",
 531 |         "mime-types": "^2.1.12"
 532 |       }
 533 |     },
 534 |     "forwarded": {
 535 |       "version": "0.1.2",
 536 |       "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
 537 |       "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
 538 |     },
 539 |     "fresh": {
 540 |       "version": "0.5.2",
 541 |       "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
 542 |       "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
 543 |     },
 544 |     "fs-minipass": {
 545 |       "version": "1.2.7",
 546 |       "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
 547 |       "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
 548 |       "requires": {
 549 |         "minipass": "^2.6.0"
 550 |       }
 551 |     },
 552 |     "fs.realpath": {
 553 |       "version": "1.0.0",
 554 |       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 555 |       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
 556 |     },
 557 |     "fstream": {
 558 |       "version": "1.0.12",
 559 |       "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
 560 |       "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
 561 |       "optional": true,
 562 |       "requires": {
 563 |         "graceful-fs": "^4.1.2",
 564 |         "inherits": "~2.0.0",
 565 |         "mkdirp": ">=0.5 0",
 566 |         "rimraf": "2"
 567 |       }
 568 |     },
 569 |     "gauge": {
 570 |       "version": "2.7.4",
 571 |       "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
 572 |       "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
 573 |       "requires": {
 574 |         "aproba": "^1.0.3",
 575 |         "console-control-strings": "^1.0.0",
 576 |         "has-unicode": "^2.0.0",
 577 |         "object-assign": "^4.1.0",
 578 |         "signal-exit": "^3.0.0",
 579 |         "string-width": "^1.0.1",
 580 |         "strip-ansi": "^3.0.1",
 581 |         "wide-align": "^1.1.0"
 582 |       }
 583 |     },
 584 |     "gaxios": {
 585 |       "version": "3.1.0",
 586 |       "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.1.0.tgz",
 587 |       "integrity": "sha512-DDTn3KXVJJigtz+g0J3vhcfbDbKtAroSTxauWsdnP57sM5KZ3d2c/3D9RKFJ86s43hfw6WULg6TXYw/AYiBlpA==",
 588 |       "requires": {
 589 |         "abort-controller": "^3.0.0",
 590 |         "extend": "^3.0.2",
 591 |         "https-proxy-agent": "^5.0.0",
 592 |         "is-stream": "^2.0.0",
 593 |         "node-fetch": "^2.3.0"
 594 |       }
 595 |     },
 596 |     "gcp-metadata": {
 597 |       "version": "4.1.4",
 598 |       "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.1.4.tgz",
 599 |       "integrity": "sha512-5J/GIH0yWt/56R3dNaNWPGQ/zXsZOddYECfJaqxFWgrZ9HC2Kvc5vl9upOgUUHKzURjAVf2N+f6tEJiojqXUuA==",
 600 |       "requires": {
 601 |         "gaxios": "^3.0.0",
 602 |         "json-bigint": "^1.0.0"
 603 |       }
 604 |     },
 605 |     "getpass": {
 606 |       "version": "0.1.7",
 607 |       "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
 608 |       "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
 609 |       "optional": true,
 610 |       "requires": {
 611 |         "assert-plus": "^1.0.0"
 612 |       }
 613 |     },
 614 |     "glob": {
 615 |       "version": "7.1.6",
 616 |       "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
 617 |       "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
 618 |       "requires": {
 619 |         "fs.realpath": "^1.0.0",
 620 |         "inflight": "^1.0.4",
 621 |         "inherits": "2",
 622 |         "minimatch": "^3.0.4",
 623 |         "once": "^1.3.0",
 624 |         "path-is-absolute": "^1.0.0"
 625 |       }
 626 |     },
 627 |     "google-auth-library": {
 628 |       "version": "6.0.6",
 629 |       "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.0.6.tgz",
 630 |       "integrity": "sha512-fWYdRdg55HSJoRq9k568jJA1lrhg9i2xgfhVIMJbskUmbDpJGHsbv9l41DGhCDXM21F9Kn4kUwdysgxSYBYJUw==",
 631 |       "requires": {
 632 |         "arrify": "^2.0.0",
 633 |         "base64-js": "^1.3.0",
 634 |         "ecdsa-sig-formatter": "^1.0.11",
 635 |         "fast-text-encoding": "^1.0.0",
 636 |         "gaxios": "^3.0.0",
 637 |         "gcp-metadata": "^4.1.0",
 638 |         "gtoken": "^5.0.0",
 639 |         "jws": "^4.0.0",
 640 |         "lru-cache": "^6.0.0"
 641 |       }
 642 |     },
 643 |     "google-p12-pem": {
 644 |       "version": "3.0.3",
 645 |       "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz",
 646 |       "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==",
 647 |       "requires": {
 648 |         "node-forge": "^0.10.0"
 649 |       }
 650 |     },
 651 |     "graceful-fs": {
 652 |       "version": "4.2.4",
 653 |       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
 654 |       "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
 655 |       "optional": true
 656 |     },
 657 |     "gtoken": {
 658 |       "version": "5.0.4",
 659 |       "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.4.tgz",
 660 |       "integrity": "sha512-U9wnSp4GZ7ov6zRdPuRHG4TuqEWqRRgT1gfXGNArhzBUn9byrPeH8uTmBWU/ZiWJJvTEmkjhDIC3mqHWdVi3xQ==",
 661 |       "requires": {
 662 |         "gaxios": "^3.0.0",
 663 |         "google-p12-pem": "^3.0.3",
 664 |         "jws": "^4.0.0",
 665 |         "mime": "^2.2.0"
 666 |       },
 667 |       "dependencies": {
 668 |         "mime": {
 669 |           "version": "2.4.6",
 670 |           "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
 671 |           "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
 672 |         }
 673 |       }
 674 |     },
 675 |     "har-schema": {
 676 |       "version": "2.0.0",
 677 |       "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
 678 |       "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
 679 |       "optional": true
 680 |     },
 681 |     "har-validator": {
 682 |       "version": "5.1.5",
 683 |       "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
 684 |       "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
 685 |       "optional": true,
 686 |       "requires": {
 687 |         "ajv": "^6.12.3",
 688 |         "har-schema": "^2.0.0"
 689 |       }
 690 |     },
 691 |     "has-flag": {
 692 |       "version": "3.0.0",
 693 |       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
 694 |       "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
 695 |     },
 696 |     "has-unicode": {
 697 |       "version": "2.0.1",
 698 |       "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
 699 |       "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
 700 |     },
 701 |     "http-errors": {
 702 |       "version": "1.7.2",
 703 |       "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
 704 |       "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
 705 |       "requires": {
 706 |         "depd": "~1.1.2",
 707 |         "inherits": "2.0.3",
 708 |         "setprototypeof": "1.1.1",
 709 |         "statuses": ">= 1.5.0 < 2",
 710 |         "toidentifier": "1.0.0"
 711 |       }
 712 |     },
 713 |     "http-signature": {
 714 |       "version": "1.2.0",
 715 |       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
 716 |       "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
 717 |       "optional": true,
 718 |       "requires": {
 719 |         "assert-plus": "^1.0.0",
 720 |         "jsprim": "^1.2.2",
 721 |         "sshpk": "^1.7.0"
 722 |       }
 723 |     },
 724 |     "https": {
 725 |       "version": "1.0.0",
 726 |       "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz",
 727 |       "integrity": "sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q="
 728 |     },
 729 |     "https-proxy-agent": {
 730 |       "version": "5.0.0",
 731 |       "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
 732 |       "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
 733 |       "requires": {
 734 |         "agent-base": "6",
 735 |         "debug": "4"
 736 |       },
 737 |       "dependencies": {
 738 |         "debug": {
 739 |           "version": "4.1.1",
 740 |           "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
 741 |           "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
 742 |           "requires": {
 743 |             "ms": "^2.1.1"
 744 |           }
 745 |         },
 746 |         "ms": {
 747 |           "version": "2.1.2",
 748 |           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
 749 |           "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
 750 |         }
 751 |       }
 752 |     },
 753 |     "iconv-lite": {
 754 |       "version": "0.4.24",
 755 |       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
 756 |       "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
 757 |       "requires": {
 758 |         "safer-buffer": ">= 2.1.2 < 3"
 759 |       }
 760 |     },
 761 |     "ignore-walk": {
 762 |       "version": "3.0.3",
 763 |       "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
 764 |       "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
 765 |       "requires": {
 766 |         "minimatch": "^3.0.4"
 767 |       }
 768 |     },
 769 |     "inflight": {
 770 |       "version": "1.0.6",
 771 |       "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
 772 |       "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
 773 |       "requires": {
 774 |         "once": "^1.3.0",
 775 |         "wrappy": "1"
 776 |       }
 777 |     },
 778 |     "inherits": {
 779 |       "version": "2.0.3",
 780 |       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
 781 |       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
 782 |     },
 783 |     "ini": {
 784 |       "version": "1.3.5",
 785 |       "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
 786 |       "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
 787 |     },
 788 |     "ipaddr.js": {
 789 |       "version": "1.9.1",
 790 |       "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
 791 |       "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
 792 |     },
 793 |     "is-fullwidth-code-point": {
 794 |       "version": "1.0.0",
 795 |       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
 796 |       "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
 797 |       "requires": {
 798 |         "number-is-nan": "^1.0.0"
 799 |       }
 800 |     },
 801 |     "is-stream": {
 802 |       "version": "2.0.0",
 803 |       "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
 804 |       "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
 805 |     },
 806 |     "is-typedarray": {
 807 |       "version": "1.0.0",
 808 |       "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
 809 |       "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
 810 |       "optional": true
 811 |     },
 812 |     "isarray": {
 813 |       "version": "1.0.0",
 814 |       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
 815 |       "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
 816 |     },
 817 |     "isexe": {
 818 |       "version": "2.0.0",
 819 |       "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
 820 |       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
 821 |       "optional": true
 822 |     },
 823 |     "isstream": {
 824 |       "version": "0.1.2",
 825 |       "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
 826 |       "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
 827 |       "optional": true
 828 |     },
 829 |     "jake": {
 830 |       "version": "10.8.2",
 831 |       "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
 832 |       "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
 833 |       "requires": {
 834 |         "async": "0.9.x",
 835 |         "chalk": "^2.4.2",
 836 |         "filelist": "^1.0.1",
 837 |         "minimatch": "^3.0.4"
 838 |       }
 839 |     },
 840 |     "jsbn": {
 841 |       "version": "0.1.1",
 842 |       "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
 843 |       "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
 844 |       "optional": true
 845 |     },
 846 |     "json-bigint": {
 847 |       "version": "1.0.0",
 848 |       "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
 849 |       "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
 850 |       "requires": {
 851 |         "bignumber.js": "^9.0.0"
 852 |       }
 853 |     },
 854 |     "json-schema": {
 855 |       "version": "0.2.3",
 856 |       "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
 857 |       "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
 858 |       "optional": true
 859 |     },
 860 |     "json-schema-traverse": {
 861 |       "version": "0.4.1",
 862 |       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
 863 |       "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
 864 |       "optional": true
 865 |     },
 866 |     "json-stringify-safe": {
 867 |       "version": "5.0.1",
 868 |       "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
 869 |       "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
 870 |       "optional": true
 871 |     },
 872 |     "jsonwebtoken": {
 873 |       "version": "8.5.1",
 874 |       "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
 875 |       "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
 876 |       "requires": {
 877 |         "jws": "^3.2.2",
 878 |         "lodash.includes": "^4.3.0",
 879 |         "lodash.isboolean": "^3.0.3",
 880 |         "lodash.isinteger": "^4.0.4",
 881 |         "lodash.isnumber": "^3.0.3",
 882 |         "lodash.isplainobject": "^4.0.6",
 883 |         "lodash.isstring": "^4.0.1",
 884 |         "lodash.once": "^4.0.0",
 885 |         "ms": "^2.1.1",
 886 |         "semver": "^5.6.0"
 887 |       },
 888 |       "dependencies": {
 889 |         "jwa": {
 890 |           "version": "1.4.1",
 891 |           "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
 892 |           "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
 893 |           "requires": {
 894 |             "buffer-equal-constant-time": "1.0.1",
 895 |             "ecdsa-sig-formatter": "1.0.11",
 896 |             "safe-buffer": "^5.0.1"
 897 |           }
 898 |         },
 899 |         "jws": {
 900 |           "version": "3.2.2",
 901 |           "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
 902 |           "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
 903 |           "requires": {
 904 |             "jwa": "^1.4.1",
 905 |             "safe-buffer": "^5.0.1"
 906 |           }
 907 |         },
 908 |         "ms": {
 909 |           "version": "2.1.2",
 910 |           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
 911 |           "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
 912 |         }
 913 |       }
 914 |     },
 915 |     "jsprim": {
 916 |       "version": "1.4.1",
 917 |       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
 918 |       "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
 919 |       "optional": true,
 920 |       "requires": {
 921 |         "assert-plus": "1.0.0",
 922 |         "extsprintf": "1.3.0",
 923 |         "json-schema": "0.2.3",
 924 |         "verror": "1.10.0"
 925 |       }
 926 |     },
 927 |     "jwa": {
 928 |       "version": "2.0.0",
 929 |       "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
 930 |       "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
 931 |       "requires": {
 932 |         "buffer-equal-constant-time": "1.0.1",
 933 |         "ecdsa-sig-formatter": "1.0.11",
 934 |         "safe-buffer": "^5.0.1"
 935 |       }
 936 |     },
 937 |     "jws": {
 938 |       "version": "4.0.0",
 939 |       "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
 940 |       "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
 941 |       "requires": {
 942 |         "jwa": "^2.0.0",
 943 |         "safe-buffer": "^5.0.1"
 944 |       }
 945 |     },
 946 |     "lodash.includes": {
 947 |       "version": "4.3.0",
 948 |       "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
 949 |       "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
 950 |     },
 951 |     "lodash.isboolean": {
 952 |       "version": "3.0.3",
 953 |       "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
 954 |       "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
 955 |     },
 956 |     "lodash.isinteger": {
 957 |       "version": "4.0.4",
 958 |       "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
 959 |       "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
 960 |     },
 961 |     "lodash.isnumber": {
 962 |       "version": "3.0.3",
 963 |       "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
 964 |       "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
 965 |     },
 966 |     "lodash.isplainobject": {
 967 |       "version": "4.0.6",
 968 |       "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
 969 |       "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
 970 |     },
 971 |     "lodash.isstring": {
 972 |       "version": "4.0.1",
 973 |       "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
 974 |       "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
 975 |     },
 976 |     "lodash.once": {
 977 |       "version": "4.1.1",
 978 |       "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
 979 |       "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
 980 |     },
 981 |     "lru-cache": {
 982 |       "version": "6.0.0",
 983 |       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
 984 |       "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
 985 |       "requires": {
 986 |         "yallist": "^4.0.0"
 987 |       }
 988 |     },
 989 |     "media-typer": {
 990 |       "version": "0.3.0",
 991 |       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
 992 |       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
 993 |     },
 994 |     "merge-descriptors": {
 995 |       "version": "1.0.1",
 996 |       "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
 997 |       "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
 998 |     },
 999 |     "methods": {
1000 |       "version": "1.1.2",
1001 |       "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
1002 |       "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
1003 |     },
1004 |     "mime": {
1005 |       "version": "1.6.0",
1006 |       "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
1007 |       "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
1008 |     },
1009 |     "mime-db": {
1010 |       "version": "1.44.0",
1011 |       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
1012 |       "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
1013 |     },
1014 |     "mime-types": {
1015 |       "version": "2.1.27",
1016 |       "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
1017 |       "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
1018 |       "requires": {
1019 |         "mime-db": "1.44.0"
1020 |       }
1021 |     },
1022 |     "minimatch": {
1023 |       "version": "3.0.4",
1024 |       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
1025 |       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
1026 |       "requires": {
1027 |         "brace-expansion": "^1.1.7"
1028 |       }
1029 |     },
1030 |     "minimist": {
1031 |       "version": "1.2.5",
1032 |       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
1033 |       "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
1034 |     },
1035 |     "minipass": {
1036 |       "version": "2.9.0",
1037 |       "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
1038 |       "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
1039 |       "requires": {
1040 |         "safe-buffer": "^5.1.2",
1041 |         "yallist": "^3.0.0"
1042 |       },
1043 |       "dependencies": {
1044 |         "yallist": {
1045 |           "version": "3.1.1",
1046 |           "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
1047 |           "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
1048 |         }
1049 |       }
1050 |     },
1051 |     "minizlib": {
1052 |       "version": "1.3.3",
1053 |       "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
1054 |       "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
1055 |       "requires": {
1056 |         "minipass": "^2.9.0"
1057 |       }
1058 |     },
1059 |     "mkdirp": {
1060 |       "version": "0.5.5",
1061 |       "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
1062 |       "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
1063 |       "requires": {
1064 |         "minimist": "^1.2.5"
1065 |       }
1066 |     },
1067 |     "ms": {
1068 |       "version": "2.0.0",
1069 |       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
1070 |       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
1071 |     },
1072 |     "needle": {
1073 |       "version": "2.5.2",
1074 |       "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz",
1075 |       "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==",
1076 |       "requires": {
1077 |         "debug": "^3.2.6",
1078 |         "iconv-lite": "^0.4.4",
1079 |         "sax": "^1.2.4"
1080 |       },
1081 |       "dependencies": {
1082 |         "debug": {
1083 |           "version": "3.2.6",
1084 |           "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
1085 |           "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
1086 |           "requires": {
1087 |             "ms": "^2.1.1"
1088 |           }
1089 |         },
1090 |         "ms": {
1091 |           "version": "2.1.2",
1092 |           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1093 |           "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
1094 |         }
1095 |       }
1096 |     },
1097 |     "negotiator": {
1098 |       "version": "0.6.2",
1099 |       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
1100 |       "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
1101 |     },
1102 |     "node-addon-api": {
1103 |       "version": "2.0.0",
1104 |       "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz",
1105 |       "integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA=="
1106 |     },
1107 |     "node-fetch": {
1108 |       "version": "2.6.0",
1109 |       "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
1110 |       "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
1111 |     },
1112 |     "node-forge": {
1113 |       "version": "0.10.0",
1114 |       "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
1115 |       "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
1116 |     },
1117 |     "node-gyp": {
1118 |       "version": "3.8.0",
1119 |       "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
1120 |       "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
1121 |       "optional": true,
1122 |       "requires": {
1123 |         "fstream": "^1.0.0",
1124 |         "glob": "^7.0.3",
1125 |         "graceful-fs": "^4.1.2",
1126 |         "mkdirp": "^0.5.0",
1127 |         "nopt": "2 || 3",
1128 |         "npmlog": "0 || 1 || 2 || 3 || 4",
1129 |         "osenv": "0",
1130 |         "request": "^2.87.0",
1131 |         "rimraf": "2",
1132 |         "semver": "~5.3.0",
1133 |         "tar": "^2.0.0",
1134 |         "which": "1"
1135 |       },
1136 |       "dependencies": {
1137 |         "semver": {
1138 |           "version": "5.3.0",
1139 |           "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
1140 |           "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
1141 |           "optional": true
1142 |         }
1143 |       }
1144 |     },
1145 |     "node-pre-gyp": {
1146 |       "version": "0.11.0",
1147 |       "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz",
1148 |       "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==",
1149 |       "requires": {
1150 |         "detect-libc": "^1.0.2",
1151 |         "mkdirp": "^0.5.1",
1152 |         "needle": "^2.2.1",
1153 |         "nopt": "^4.0.1",
1154 |         "npm-packlist": "^1.1.6",
1155 |         "npmlog": "^4.0.2",
1156 |         "rc": "^1.2.7",
1157 |         "rimraf": "^2.6.1",
1158 |         "semver": "^5.3.0",
1159 |         "tar": "^4"
1160 |       },
1161 |       "dependencies": {
1162 |         "nopt": {
1163 |           "version": "4.0.3",
1164 |           "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz",
1165 |           "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==",
1166 |           "requires": {
1167 |             "abbrev": "1",
1168 |             "osenv": "^0.1.4"
1169 |           }
1170 |         },
1171 |         "tar": {
1172 |           "version": "4.4.13",
1173 |           "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
1174 |           "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
1175 |           "requires": {
1176 |             "chownr": "^1.1.1",
1177 |             "fs-minipass": "^1.2.5",
1178 |             "minipass": "^2.8.6",
1179 |             "minizlib": "^1.2.1",
1180 |             "mkdirp": "^0.5.0",
1181 |             "safe-buffer": "^5.1.2",
1182 |             "yallist": "^3.0.3"
1183 |           }
1184 |         },
1185 |         "yallist": {
1186 |           "version": "3.1.1",
1187 |           "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
1188 |           "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
1189 |         }
1190 |       }
1191 |     },
1192 |     "nopt": {
1193 |       "version": "3.0.6",
1194 |       "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
1195 |       "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
1196 |       "optional": true,
1197 |       "requires": {
1198 |         "abbrev": "1"
1199 |       }
1200 |     },
1201 |     "npm-bundled": {
1202 |       "version": "1.1.1",
1203 |       "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
1204 |       "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
1205 |       "requires": {
1206 |         "npm-normalize-package-bin": "^1.0.1"
1207 |       }
1208 |     },
1209 |     "npm-normalize-package-bin": {
1210 |       "version": "1.0.1",
1211 |       "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
1212 |       "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA=="
1213 |     },
1214 |     "npm-packlist": {
1215 |       "version": "1.4.8",
1216 |       "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz",
1217 |       "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==",
1218 |       "requires": {
1219 |         "ignore-walk": "^3.0.1",
1220 |         "npm-bundled": "^1.0.1",
1221 |         "npm-normalize-package-bin": "^1.0.1"
1222 |       }
1223 |     },
1224 |     "npmlog": {
1225 |       "version": "4.1.2",
1226 |       "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
1227 |       "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
1228 |       "requires": {
1229 |         "are-we-there-yet": "~1.1.2",
1230 |         "console-control-strings": "~1.1.0",
1231 |         "gauge": "~2.7.3",
1232 |         "set-blocking": "~2.0.0"
1233 |       }
1234 |     },
1235 |     "number-is-nan": {
1236 |       "version": "1.0.1",
1237 |       "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
1238 |       "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
1239 |     },
1240 |     "oauth-sign": {
1241 |       "version": "0.9.0",
1242 |       "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
1243 |       "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
1244 |       "optional": true
1245 |     },
1246 |     "object-assign": {
1247 |       "version": "4.1.1",
1248 |       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1249 |       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
1250 |     },
1251 |     "on-finished": {
1252 |       "version": "2.3.0",
1253 |       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
1254 |       "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
1255 |       "requires": {
1256 |         "ee-first": "1.1.1"
1257 |       }
1258 |     },
1259 |     "once": {
1260 |       "version": "1.4.0",
1261 |       "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1262 |       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
1263 |       "requires": {
1264 |         "wrappy": "1"
1265 |       }
1266 |     },
1267 |     "os-homedir": {
1268 |       "version": "1.0.2",
1269 |       "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
1270 |       "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
1271 |     },
1272 |     "os-tmpdir": {
1273 |       "version": "1.0.2",
1274 |       "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
1275 |       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
1276 |     },
1277 |     "osenv": {
1278 |       "version": "0.1.5",
1279 |       "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
1280 |       "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
1281 |       "requires": {
1282 |         "os-homedir": "^1.0.0",
1283 |         "os-tmpdir": "^1.0.0"
1284 |       }
1285 |     },
1286 |     "parseurl": {
1287 |       "version": "1.3.3",
1288 |       "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
1289 |       "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
1290 |     },
1291 |     "path-is-absolute": {
1292 |       "version": "1.0.1",
1293 |       "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1294 |       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
1295 |     },
1296 |     "path-to-regexp": {
1297 |       "version": "0.1.7",
1298 |       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
1299 |       "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
1300 |     },
1301 |     "performance-now": {
1302 |       "version": "2.1.0",
1303 |       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
1304 |       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
1305 |       "optional": true
1306 |     },
1307 |     "process-nextick-args": {
1308 |       "version": "2.0.1",
1309 |       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
1310 |       "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
1311 |     },
1312 |     "proxy-addr": {
1313 |       "version": "2.0.6",
1314 |       "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
1315 |       "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
1316 |       "requires": {
1317 |         "forwarded": "~0.1.2",
1318 |         "ipaddr.js": "1.9.1"
1319 |       }
1320 |     },
1321 |     "psl": {
1322 |       "version": "1.8.0",
1323 |       "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
1324 |       "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
1325 |       "optional": true
1326 |     },
1327 |     "punycode": {
1328 |       "version": "2.1.1",
1329 |       "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
1330 |       "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
1331 |       "optional": true
1332 |     },
1333 |     "qs": {
1334 |       "version": "6.7.0",
1335 |       "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
1336 |       "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
1337 |     },
1338 |     "range-parser": {
1339 |       "version": "1.2.1",
1340 |       "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
1341 |       "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
1342 |     },
1343 |     "raw-body": {
1344 |       "version": "2.4.0",
1345 |       "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
1346 |       "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
1347 |       "requires": {
1348 |         "bytes": "3.1.0",
1349 |         "http-errors": "1.7.2",
1350 |         "iconv-lite": "0.4.24",
1351 |         "unpipe": "1.0.0"
1352 |       }
1353 |     },
1354 |     "rc": {
1355 |       "version": "1.2.8",
1356 |       "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
1357 |       "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
1358 |       "requires": {
1359 |         "deep-extend": "^0.6.0",
1360 |         "ini": "~1.3.0",
1361 |         "minimist": "^1.2.0",
1362 |         "strip-json-comments": "~2.0.1"
1363 |       }
1364 |     },
1365 |     "readable-stream": {
1366 |       "version": "2.3.7",
1367 |       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
1368 |       "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
1369 |       "requires": {
1370 |         "core-util-is": "~1.0.0",
1371 |         "inherits": "~2.0.3",
1372 |         "isarray": "~1.0.0",
1373 |         "process-nextick-args": "~2.0.0",
1374 |         "safe-buffer": "~5.1.1",
1375 |         "string_decoder": "~1.1.1",
1376 |         "util-deprecate": "~1.0.1"
1377 |       }
1378 |     },
1379 |     "request": {
1380 |       "version": "2.88.2",
1381 |       "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
1382 |       "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
1383 |       "optional": true,
1384 |       "requires": {
1385 |         "aws-sign2": "~0.7.0",
1386 |         "aws4": "^1.8.0",
1387 |         "caseless": "~0.12.0",
1388 |         "combined-stream": "~1.0.6",
1389 |         "extend": "~3.0.2",
1390 |         "forever-agent": "~0.6.1",
1391 |         "form-data": "~2.3.2",
1392 |         "har-validator": "~5.1.3",
1393 |         "http-signature": "~1.2.0",
1394 |         "is-typedarray": "~1.0.0",
1395 |         "isstream": "~0.1.2",
1396 |         "json-stringify-safe": "~5.0.1",
1397 |         "mime-types": "~2.1.19",
1398 |         "oauth-sign": "~0.9.0",
1399 |         "performance-now": "^2.1.0",
1400 |         "qs": "~6.5.2",
1401 |         "safe-buffer": "^5.1.2",
1402 |         "tough-cookie": "~2.5.0",
1403 |         "tunnel-agent": "^0.6.0",
1404 |         "uuid": "^3.3.2"
1405 |       },
1406 |       "dependencies": {
1407 |         "qs": {
1408 |           "version": "6.5.2",
1409 |           "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
1410 |           "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
1411 |           "optional": true
1412 |         }
1413 |       }
1414 |     },
1415 |     "rimraf": {
1416 |       "version": "2.7.1",
1417 |       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
1418 |       "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
1419 |       "requires": {
1420 |         "glob": "^7.1.3"
1421 |       }
1422 |     },
1423 |     "safe-buffer": {
1424 |       "version": "5.1.2",
1425 |       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
1426 |       "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
1427 |     },
1428 |     "safer-buffer": {
1429 |       "version": "2.1.2",
1430 |       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1431 |       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1432 |     },
1433 |     "sax": {
1434 |       "version": "1.2.4",
1435 |       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
1436 |       "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
1437 |     },
1438 |     "semver": {
1439 |       "version": "5.7.1",
1440 |       "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
1441 |       "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
1442 |     },
1443 |     "send": {
1444 |       "version": "0.17.1",
1445 |       "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
1446 |       "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
1447 |       "requires": {
1448 |         "debug": "2.6.9",
1449 |         "depd": "~1.1.2",
1450 |         "destroy": "~1.0.4",
1451 |         "encodeurl": "~1.0.2",
1452 |         "escape-html": "~1.0.3",
1453 |         "etag": "~1.8.1",
1454 |         "fresh": "0.5.2",
1455 |         "http-errors": "~1.7.2",
1456 |         "mime": "1.6.0",
1457 |         "ms": "2.1.1",
1458 |         "on-finished": "~2.3.0",
1459 |         "range-parser": "~1.2.1",
1460 |         "statuses": "~1.5.0"
1461 |       },
1462 |       "dependencies": {
1463 |         "ms": {
1464 |           "version": "2.1.1",
1465 |           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
1466 |           "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
1467 |         }
1468 |       }
1469 |     },
1470 |     "serve-static": {
1471 |       "version": "1.14.1",
1472 |       "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
1473 |       "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
1474 |       "requires": {
1475 |         "encodeurl": "~1.0.2",
1476 |         "escape-html": "~1.0.3",
1477 |         "parseurl": "~1.3.3",
1478 |         "send": "0.17.1"
1479 |       }
1480 |     },
1481 |     "set-blocking": {
1482 |       "version": "2.0.0",
1483 |       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
1484 |       "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
1485 |     },
1486 |     "setprototypeof": {
1487 |       "version": "1.1.1",
1488 |       "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
1489 |       "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
1490 |     },
1491 |     "signal-exit": {
1492 |       "version": "3.0.3",
1493 |       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
1494 |       "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
1495 |     },
1496 |     "sqlite3": {
1497 |       "version": "5.0.0",
1498 |       "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.0.tgz",
1499 |       "integrity": "sha512-rjvqHFUaSGnzxDy2AHCwhHy6Zp6MNJzCPGYju4kD8yi6bze4d1/zMTg6C7JI49b7/EM7jKMTvyfN/4ylBKdwfw==",
1500 |       "requires": {
1501 |         "node-addon-api": "2.0.0",
1502 |         "node-gyp": "3.x",
1503 |         "node-pre-gyp": "^0.11.0"
1504 |       }
1505 |     },
1506 |     "sshpk": {
1507 |       "version": "1.16.1",
1508 |       "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
1509 |       "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
1510 |       "optional": true,
1511 |       "requires": {
1512 |         "asn1": "~0.2.3",
1513 |         "assert-plus": "^1.0.0",
1514 |         "bcrypt-pbkdf": "^1.0.0",
1515 |         "dashdash": "^1.12.0",
1516 |         "ecc-jsbn": "~0.1.1",
1517 |         "getpass": "^0.1.1",
1518 |         "jsbn": "~0.1.0",
1519 |         "safer-buffer": "^2.0.2",
1520 |         "tweetnacl": "~0.14.0"
1521 |       }
1522 |     },
1523 |     "statuses": {
1524 |       "version": "1.5.0",
1525 |       "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
1526 |       "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
1527 |     },
1528 |     "string-width": {
1529 |       "version": "1.0.2",
1530 |       "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
1531 |       "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
1532 |       "requires": {
1533 |         "code-point-at": "^1.0.0",
1534 |         "is-fullwidth-code-point": "^1.0.0",
1535 |         "strip-ansi": "^3.0.0"
1536 |       }
1537 |     },
1538 |     "string_decoder": {
1539 |       "version": "1.1.1",
1540 |       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
1541 |       "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
1542 |       "requires": {
1543 |         "safe-buffer": "~5.1.0"
1544 |       }
1545 |     },
1546 |     "strip-ansi": {
1547 |       "version": "3.0.1",
1548 |       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
1549 |       "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
1550 |       "requires": {
1551 |         "ansi-regex": "^2.0.0"
1552 |       }
1553 |     },
1554 |     "strip-json-comments": {
1555 |       "version": "2.0.1",
1556 |       "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
1557 |       "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
1558 |     },
1559 |     "supports-color": {
1560 |       "version": "5.5.0",
1561 |       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
1562 |       "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
1563 |       "requires": {
1564 |         "has-flag": "^3.0.0"
1565 |       }
1566 |     },
1567 |     "tar": {
1568 |       "version": "2.2.2",
1569 |       "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
1570 |       "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
1571 |       "optional": true,
1572 |       "requires": {
1573 |         "block-stream": "*",
1574 |         "fstream": "^1.0.12",
1575 |         "inherits": "2"
1576 |       }
1577 |     },
1578 |     "toidentifier": {
1579 |       "version": "1.0.0",
1580 |       "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
1581 |       "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
1582 |     },
1583 |     "tough-cookie": {
1584 |       "version": "2.5.0",
1585 |       "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
1586 |       "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
1587 |       "optional": true,
1588 |       "requires": {
1589 |         "psl": "^1.1.28",
1590 |         "punycode": "^2.1.1"
1591 |       }
1592 |     },
1593 |     "tunnel-agent": {
1594 |       "version": "0.6.0",
1595 |       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
1596 |       "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
1597 |       "optional": true,
1598 |       "requires": {
1599 |         "safe-buffer": "^5.0.1"
1600 |       }
1601 |     },
1602 |     "tweetnacl": {
1603 |       "version": "0.14.5",
1604 |       "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
1605 |       "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
1606 |       "optional": true
1607 |     },
1608 |     "type-is": {
1609 |       "version": "1.6.18",
1610 |       "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
1611 |       "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
1612 |       "requires": {
1613 |         "media-typer": "0.3.0",
1614 |         "mime-types": "~2.1.24"
1615 |       }
1616 |     },
1617 |     "unpipe": {
1618 |       "version": "1.0.0",
1619 |       "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1620 |       "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
1621 |     },
1622 |     "uri-js": {
1623 |       "version": "4.4.0",
1624 |       "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
1625 |       "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
1626 |       "optional": true,
1627 |       "requires": {
1628 |         "punycode": "^2.1.0"
1629 |       }
1630 |     },
1631 |     "util-deprecate": {
1632 |       "version": "1.0.2",
1633 |       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1634 |       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
1635 |     },
1636 |     "utils-merge": {
1637 |       "version": "1.0.1",
1638 |       "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
1639 |       "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
1640 |     },
1641 |     "uuid": {
1642 |       "version": "3.4.0",
1643 |       "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
1644 |       "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
1645 |       "optional": true
1646 |     },
1647 |     "vary": {
1648 |       "version": "1.1.2",
1649 |       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
1650 |       "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
1651 |     },
1652 |     "verror": {
1653 |       "version": "1.10.0",
1654 |       "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
1655 |       "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
1656 |       "optional": true,
1657 |       "requires": {
1658 |         "assert-plus": "^1.0.0",
1659 |         "core-util-is": "1.0.2",
1660 |         "extsprintf": "^1.2.0"
1661 |       }
1662 |     },
1663 |     "which": {
1664 |       "version": "1.3.1",
1665 |       "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
1666 |       "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
1667 |       "optional": true,
1668 |       "requires": {
1669 |         "isexe": "^2.0.0"
1670 |       }
1671 |     },
1672 |     "wide-align": {
1673 |       "version": "1.1.3",
1674 |       "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
1675 |       "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
1676 |       "requires": {
1677 |         "string-width": "^1.0.2 || 2"
1678 |       }
1679 |     },
1680 |     "wrappy": {
1681 |       "version": "1.0.2",
1682 |       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1683 |       "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
1684 |     },
1685 |     "yallist": {
1686 |       "version": "4.0.0",
1687 |       "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
1688 |       "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
1689 |     }
1690 |   }
1691 | }
1692 | 


--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "login-page",
 3 |   "version": "1.0.0",
 4 |   "description": "",
 5 |   "main": "index.js",
 6 |   "scripts": {
 7 |     "test": "echo \"Error: no test specified\" && exit 1",
 8 |     "start": "node index.js"
 9 |   },
10 |   "author": "",
11 |   "license": "ISC",
12 |   "dependencies": {
13 |     "axios": "^0.20.0",
14 |     "bcryptjs": "^2.4.3",
15 |     "body-parser": "^1.19.0",
16 |     "cookie-parser": "^1.4.5",
17 |     "dotenv": "^8.2.0",
18 |     "ejs": "^3.1.5",
19 |     "express": "^4.17.1",
20 |     "google-auth-library": "^6.0.6",
21 |     "gtoken": "^5.0.4",
22 |     "https": "^1.0.0",
23 |     "jsonwebtoken": "^8.5.1",
24 |     "sqlite3": "^5.0.0"
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
 1 | 

2 | 3 |
4 | 5 |
6 | 7 |

About

8 | 9 | > This is an auth module built with nodejs.The code is modularized and will be helpful for anyone looking into exploring the below mentioned technologies, learning OAuth2 or MVC architecture in nodejs. 10 | > Have a look at https://full-auth.herokuapp.com. 11 | 12 |

Tech Stack / Tools

13 | 14 | Nodejs 15 | 16 | jQuery Ejs Express 17 | 18 | SQLite MySQL 19 | 20 |

Features

21 | 22 | >
    23 | >
  • Authentication and authorization using JWT tokens.
  • 24 | >
  • Google and Facebook Sign In.
  • 25 | >
  • Uses server side cookies
  • 26 | >
  • Saves data in SQLite database
  • 27 | >
  • Model - View - Controller Architecture
  • 28 | >
  • Responsive
  • 29 | >
30 | 31 |

To setup locally

32 | 33 | ``` 34 | 35 | git clone https://github.com/Sudheer121/Full-Auth.git 36 | npm install 37 | node dbrunonce.js (sets up SQLite database) 38 | 39 | ``` 40 | Change filename .env.example to .env 41 | 42 |
43 | 44 |

More Details

45 | 46 |

Database Tables

47 | 48 | > registration(uid, email, first_name, last_name, phone_no, signin_type) 49 | 50 | > transactions(uid, pname, pid, pprice, tdate, ttime) 51 | 52 | > uid => user id, pname => product name 53 | 54 | MySQL database can also be used instead of SQLite, nodejs mysql queries are commented below SQLite queries. 55 | 56 |

Api Routes

57 | 58 | ``` 59 | / 60 | /login 61 | /register 62 | /api/gsignin 63 | /api/fbsignin 64 | /api/pay 65 | 66 | ``` 67 |

Cookies

68 | 69 | > The website uses a Cookie called 'grishmat'. 70 | 71 | 72 |
73 | 74 | 75 |

Helpful resources for learners

76 | 77 | Learn about JWT here 78 | 79 | Learn about integrating Google Signin here 80 | 81 | Learn about integrating Facebook Signin here 82 | 83 | 84 | 85 | >

Issues and PRs are welcome

86 | -------------------------------------------------------------------------------- /tokenauth/tokenvalidation.js: -------------------------------------------------------------------------------- 1 | const jwt = require("jsonwebtoken"); 2 | const jwtsalt = process.env.JWT_SALT; 3 | 4 | module.exports = { 5 | checkToken: function(req,res,next){ 6 | token = req.cookies['grishmat']; 7 | if(token){ 8 | jwt.verify(token, jwtsalt, function(err,decoded){ 9 | if(err){ 10 | req.message = "Invalid/Expired Token" 11 | next(); 12 | } else { 13 | req.decode = decoded; // attaching decoded info in req 14 | next(); 15 | } 16 | }); 17 | } else { 18 | req.message = "Please login first"; 19 | next(); 20 | } 21 | } 22 | }; 23 | /* 24 | Decode property is attached to request(req) object if token decoding was successful 25 | Message property is attached otherwise. 26 | */ -------------------------------------------------------------------------------- /views/home.ejs: -------------------------------------------------------------------------------- 1 | <%- include('partials/header') %> 2 | Full Auth 3 | 4 | 69 | 70 | 71 | 72 | 79 |
80 |

<%= name %>

81 |
82 |
83 |
84 | Log into the website by any Signin method. 85 | Type random values in the form below/beside and click pay. 86 | Then close the page and revisit/reload the page. 87 | Then click on Get Transaction History. 88 | You will be able to view your all previous transactions. 89 | The website keeps you logged in for 7 days. 90 | This is just a demo to show that login was legit. 91 |
92 |
93 |
94 |
95 | 96 |
97 | 98 |
99 |
100 |
101 | 102 |
103 | 104 |
105 |
106 |
107 | 108 |
109 | 110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /views/login.ejs: -------------------------------------------------------------------------------- 1 | <%- include('partials/header') %> 2 | 3 | 4 | 5 | Full Auth 6 | 7 | 8 | 9 | 10 | 11 |
12 | 15 | 36 |
37 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /views/partials/header.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /views/register.ejs: -------------------------------------------------------------------------------- 1 | <%- include('partials/header') %> 2 | 3 | Full Auth 4 | 5 | 6 | 7 | 8 |
9 | 12 | 36 |
37 | 38 |
39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /views/sample.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /views/transactionsTable.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Table 7 | 25 | 26 | 27 | <% if( resultArr.length > 0 ) { %> 28 | All transactions so far 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | <% for(var i=0;i < resultArr.length;i++ ) { %> 38 | <% const obj = resultArr[i]; %> 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | <% } %> 47 |
Time Date Product Name Producut ID Product Price
<%= obj.ttime %> <%= obj.tdate %> <%= obj.pname %> <%= obj.pid %> <%= obj.pprice %>
48 | <% } else { %> 49 |

No transactions so far

50 | <% } %> 51 | 52 | 53 | --------------------------------------------------------------------------------