Related
During the launch my website i can't connection to my database. It doesn't get errors and the page is loading infinitely. Who know answer on this question give me some advise.
I work in (Node.js,PostgreSQL,Express)
from file config_db
const client_admin1 = {
user:'a_role',
database:'road_db',
password: '12345',
host:'localhost',
port:5432,
max:10,
idleTimeoutMillis: 30000
}
const pg = require("pg")
const client_login = require("../config/config_db");
searchUser(req, res) {
const db = new pg.Pool(client_login.client_admin1)
db.connect(function(err, client, done){
if(err){
return console.error('connection problems')
}
client.query('SELECT * FROM login_phone WHERE phone = $1 AND password1 = $2',[req.body.login, req.body.password], function(err, result){
done()
if (err || result.rowCount <= 0){
res.render('error_login_choice')
return console.error("")
}
if(result.rows[0].role_name === "client")
{
cln.getClients(req,res)
}
})
}
try this executeQuery method
const pg = require('pg');
const pgconfig = {
user: process.env.DATA_BASE_USER,
database: process.env.DATA_BASE_NAME,
password: process.env.DATA_BASE_PASSWORD,
host: process.env.DATA_BASE_HOST,
port: process.env.DATA_BASE_PORT,
};
console.log(`DB | Settings: ${JSON.stringify(pgconfig)}`);
const pool = new pg.Pool(pgconfig);
pool.on('connect', () => {
console.log('DB | new client connection establish.');
});
pool.on('error', err => {
console.error(`idle client error, ${err.message} | ${err.stack}`);
});
pool.connect(err => {
if (err) {
console.error(`PostgreSQL input: ${err}`);
} else console.log('DB | connection establish.');
});
const executeQuery = async(sql, data) => {
logger.debug(`sqlToDB() sql: ${sql} | data: ${data}`);
try {
const result = await pool.query(sql, data);
return result;
} catch (error) {
console.error(error.message);
}
};
module.exports = {
executeQuery,
};
usage:
const dbHandler = require('./db');
const getLogedInUser = login,password => {
const selectFieldsQuery = `'SELECT * FROM login_phone WHERE phone = $1 AND password1 = $2'`;
return dbHandler.executeQuery(selectFieldsQuery, [login,password]).then(e => e.rows);
};
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I'm working in a simple API Key authentication, I just want to verify the given key against the user provied key.
I have a seperate file with the function querying the database, and returning true/false and the user object.
But in my route.js file, the return object is undefined even tough in my auth.js file it isn't.
I tried making the the function in router.get an async function using express-promise-router and making the function an await return var user = await auth.verify(req.params.uid, req.get("token")) but I don't realy know how async works.
router.js
[...]
router.get('/list/:uid', function(req, res) {
var user = auth.verify(req.params.uid, req.get("token"))
console.log("User: " + user) // <-- Undefined
if (user.status) {
res.send("Success")
} else {
res.status(403)
res.json({status: 403, error: "Unkown User / Token"})
}
})
[...]
auth.js
var db = require('./db')
var ObjectId = require('mongodb').ObjectId;
module.exports = {
verify: (uid, key) => {
try {
var collection = db.get().collection('users')
const obj_id = new ObjectId(uid)
const query = { _id: obj_id }
collection.find(query).limit(1).toArray(function(err, user) {
var status = 0;
var usr = {};
if (err) {throw err}else{status=1}
if (user.length <= 0) {throw "NotExistingExc"; status = 0}else{
usr = user[0];
if (key != usr.api) status = 0
}
var returnObj = {
status: status,
user: usr
} /* --> Is {
status: 1,
user: {
_id: d47a2b30b3d2770606942bf0,
name: 'Sh4dow',
groups: [ 0 ],
api: 'YWFiMDI1MGE4NjAyZTg0MWE3N2U0M2I1NzEzZGE1YjE='
}
}
*/
return returnObj;
})
} catch (e) {
console.error(e)
return {
status: 0,
user: {},
error: e
}
}
}
}
db.js (Idk if needed)
var MongoClient = require('mongodb').MongoClient
var state = {
db: null,
}
exports.connect = function(url, done) {
if (state.db) return done()
MongoClient.connect(url, { useNewUrlParser: true }, function(err, db) {
if (err) return done(err)
state.db = db
done()
})
}
exports.get = function() {
return state.db.db("database")
}
exports.close = function(done) {
if (state.db) {
state.db.close(function(err, result) {
state.db = null
state.mode = null
done(err)
})
}
}
I want to have the returnObjin auth.js in the router.get of my route.js file.
Make auth.verify return a Promise which we can then await for it inside router, You can just make the callback async no need for express-promise-router
router.get('/list/:uid', async function(req, res) {
try {
var user = await auth.verify(req.params.uid, req.get("token"))
console.log("User: " + user)
if (user.status) {
res.send("Success")
} else {
res.status(403).json({status: 403, error: "Unkown User / Token"})
}
} catch (e) {
console.error(e)
res.status(/* */).json(/* */)
}
})
auth
module.exports = {
verify: (uid, key) => new Promise((resolve, reject) => {
var collection = db.get().collection('users')
const obj_id = new ObjectId(uid)
const query = { _id: obj_id }
collection.find(query).limit(1).toArray(function(err, user) {
var status = 0;
var usr = {};
if (err) {
reject(err)
return
} else {
status = 1
}
if (user.length <= 0) {
reject(new Error("NotExistingExc"))
return
} else {
usr = user[0]
if (key != usr.api) status = 0
}
var returnObj = {
status: status,
user: usr
}
resolve(returnObj);
})
}
}
In short, the reason you get undefined is because the code in auth.js is asyncronous. But you're really close. The toArray method in MongoDB returns a promise, so you need to make sure you return that promise and then use it in the router correctly.
In auth.js, make sure verify returns a promise - just add return!
return collection.find(query).limit(1).toArray(...)
And then, change your usage of the verify to the async/await you originally tried:
router.get('/list/:uid', async function(req, res) {
var user = await auth.verify(req.params.uid, req.get("token"))
// More code here...
})
I've got a method in a class which does query an ActiveDirectory.
Therefore I'm using 'activedirectory2' npm package.
I successfully authenticated and successfully logged my result to console.
Now that I have instanciated my class and have tried to call the method, I'm not abled to get a non-empty result.
I tried it with getters/setters to make the _result value available after instaciating the class.
I tried to solve my issue with research on asynchronous calls, but obviously wasn't able to ask the right question.
class Activedirectory
var ActiveDirectory = require("activedirectory2");
class AuthenticateWithLDAP {
constructor(user, password){
this._result = [];
this.user = user;
this.password = password;
this.config = {
url: "ldaps://someldap",
baseDN: "somebasdn",
username: this.user,
password: this.password,
filter: 'somefilter',
}
this.ad = new ActiveDirectory(this.config);
}
//Auth Method
auth() {
var result = this._result;
this.config.entryParser = function(entry,raw,callback){
if(entry.hasOwnProperty('info')) {
result.push(entry.info);
this._result = result;
}
callback(entry);
}
this.ad.authenticate(config.username, config.password, (err,auth)=>{
if (err) {
//some error handling
}
if (auth) {
this.ad.find(config,async (err, userDetails) => {
var result = this._result;
{
if (err) {
//some error handling
}
if(!userDetails) {
console.log("No users found.");
} else {
this._result = result[0]; //I want this result!
console.log('result: ', this._result);
return await this._result;
}
}
})
} else {
console.log("Authentication failed!");
}
});
}
//getter/setter
get result(){
return this._result;
}
set result(value) {
this._result.push(value);
}
}
module.exports = AuthenticateWithLDAP;
route module
const express = require('express');
const AuthwithLDAP = require('AuthenticateWithLDAP');
const router = express.Router();
router.post('/', async (req,res,next) => {
let x = async ()=> {
authwithldap = new AuthwithLDAP(req.body.user,req.body.password);
return await authwithldap.auth();
}
x().then((res)=>{
console.log('res: ', res); //always []
})
})
I expected to be able to use the _result value of AuthenticateWithLDAP class in my router.post method handler.
Actually i only get [] (empty array) in router.post.
Could you please tell me how to alter the value _result in a way, so that the instance of the class knows it and can use it outside the class itself.
Thank you very much.
Micha
I am not 100% sure but I think this should work.
In your code you cant return the result because the return is in a callback.
There are to ways to fix that.
Pass a callback to the auth() method (This is bad since callbacks suck)
Return a promise and that resolves to the result
I've decided to go for promises.
var ActiveDirectory = require("activedirectory2");
class AuthenticateWithLDAP {
constructor(user, password){
this._result = [];
this.user = user;
this.password = password;
this.config = {
url: "ldaps://someldap",
baseDN: "somebasdn",
username: this.user,
password: this.password,
filter: 'somefilter',
}
this.ad = new ActiveDirectory(this.config);
}
//Auth Method
auth() {
return new Promise((resolve, reject) => {
this.ad.authenticate(config.username, config.password, (err,auth)=>{
if (err) {
//Call reject here
}
if (auth) {
this.ad.find(config,async (err, userDetails) => {
var result = this._result;
{
if (err) {
//some error handling
}
if(!userDetails) {
console.log("No users found.");
} else {
this._result = result[0]; //I want this result!
resolve(await this._result);
}
}
})
} else {
console.log("Authentication failed!");
}
});
});
}
}
module.exports = AuthenticateWithLDAP;
const express = require('express');
const AuthwithLDAP = require('AuthenticateWithLDAP');
const router = express.Router();
router.post('/', async (req,res,next) => {
/* This code can be simplifed
let x = async () => {
authwithldap = new AuthwithLDAP(req.body.user,req.body.password);
return await authwithldap.auth();
}
x().then((res)=>{
console.log('res: ', res); //always []
})
*/
(async () => {
authwithldap = new AuthwithLDAP(req.body.user,req.body.password);
var res = await authwithldap.auth();
console.log('res: ', res);
})();
})
Could you try to add syntax "await" like this?
await x().then((res)=>{
console.log('res: ', res); //always []
})
As your "x" method is in async mode, maybe you have to wait for the Promise to be resolved...
My question is similar to this.
However, mine runs in Node.js and it seems like a bit more complicated.
The server side wasn't built by me, but someone else that I can't contact. And he wrote code very differently.
And I have db.js and it looks like this:
And routes/email.js it uses db.js like this:
And when I click a button. I get this error:
db.emailRequest is not a function
in db.js, at the end of the file. It originally had this:
module.exports = new dbHelper;
And my style to use db.js in routers.
db.get().query(sql, input, function(err,res){
//TODO:
});
But it didn't work. So, I changed the end of db.js like this:
exports.get = function(){
console.log("exports.get");
return pool;
}
And also added some code in app.js like this:
db.connect(function(err){
if(err){
console.log('Unable to connect to MariaDB');
process.exit(1);
}
});
What should I do?
The full code of db.js is here:
const mariadb = require('mariadb');
var pool;
exports.connect = function(done){
console.log("Trying to connect DB...");
pool = mariadb.createPool({
host: 'localhost',
user: 'root',
password: 'xxxxxxx',
database:"XXXXX",
connectionLimit: 5 // Why 5 ???
});
pool.getConnection()
.then(conn => {
console.log("DB connected. id: " + conn.threadId);
conn.end(); //release to pool
}).catch(err => {
console.log("DB failed connection: " + err);
});
}
function makeToken(){
console.log("makeToken()");
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
for(var i=0;i<32;i++){
text+=possible.charAt(Math.floor(Math.random()*possible.length));
}
return text;
}
function dbHelper() {
console.log("dbHelper()");
this.emailRequest = function(email,num){
console.log("emailRequest");
pool.getConnection().then(conn => {
conn.query("INSERT INTO email_verification(email, code) VALUES(?,?)",[email,num]);
conn.end(); //release to pool
})
.catch(err => {
console.log("not connected due to error: " + err);
});
}
// wait and process until getting return value because rv is needed.
this.verify = async function(email,num){
console.log("verify");
let conn;
var result = false;
try {
conn = await pool.getConnection();
// within 3minutes
const rows = await conn.query("SELECT count(*) FROM email_verificaiton WHERE email=? AND code=? AND req_time >= NOW() - INTERVAL 3 MINUTE",[email,num]);
if(rows[0]["count(*)"]>0){
result = true;
}
} catch (err) {
throw err;
} finally {
if (conn) conn.end();
}
return result;
}
this.verifyUpdate = function(email,num){
console.log("verifyUpdate");
pool.getConnection()
.then(conn => {
conn.query("UPDATE email_verification SET status = 1 WHERE email=? AND code=?",[email,num]);
conn.end(); //release to pool
})
.catch(err => {
console.log("not connected due to error: " + err);
});
}
// wait and process until getting return value because rv is needed.
this.emailRegister = async function(email,pass,nick,devid){
console.log("emailRegister");
let conn;
var result;
try {
conn = await pool.getConnection();
var rows = await conn.query("SELECT count(*) FROM email_verification WHERE email=? AND status = 1",[email]);
if(rows[0]["count(*)"]>0){
rows = await conn.query("SELECT count(*) FROM member WHERE email=?",[email]);
if(rows[0]["count(*)"]==0){
var token = makeToken();
rows = await conn.query("INSERT INTO member (email,password,username,device_id,login_method,token) VALUES(?,?,?,?,0,?)",[email,pass,nick,devid,token]);
if(rows["affectedRows"]>0){
result = {result:true, code:200, message: "success",data:[{email:email,token:token}]};
} else{
result = {result:false,code:401, message:"db error"};
}
}else {
result = {result:false,code:402, message:"already registered id"};
}
} else {
result = {result:false,code:403, meesage:"email not verified"};
}
} catch (err) {
throw err;
} finally {
if (conn) conn.end();
}
return result;
}
// wait and process until getting return value because rv is needed.
this.emailLogin = async function(email,pass,devid){
console.log("emailLogin");
let conn;
var result;
try {
conn = await pool.getConnection();
rows = await conn.query("SELECT * FROM member WHERE email=?",[email]);
if(rows.length==1){
if(rows[0]["password"]==pass){
var token = makeToken();
rows = await conn.query("UPDATE member SET device_id = ?, token = ? WHERE email=?",[devid,token,email]);
console.log(rows)
if(rows["affectedRows"]>0){
result = {result:true,message:"Sign up Success.", code:200, data:[{email:email,token:token}]};
} else{
result = {result:false,message:"db error",code:401};
}
} else {
result = {result:false,message:"wrong password",code:402};
}
}else {
result = {result:false,message:"not registered id",code:403};
}
} catch (err) {
throw err;
} finally {
if (conn) conn.end();
}
return result;
}
}
//module.exports = new dbHelper;
exports.get = function(){
console.log("exports.get");
return pool;
}
I've been slowly learning node.js so that I can integrate things better between a lot of our current ops (mysql) and Xero accounting.
I have several tables in mysql, one each for ["invoices","accounts","items","organisations","receipts","taxRates","users","trackingCategories"]
and each of those tables has a JSON column with the same name as the table it's in. This is NOT a json question.
Sending a query like ""select "+ wewant1[i] + " from "+wewant1[i]" is basically simple "select invoices from invoices" and easy to iterate through.
I can get the mysql results to list, but need to get each separate "list" as an array of results.
I would ultimately like to be able to reference the results from "select invoices from invoices" as an "invoices" array in node (invoices[0], invoices[1], etc).
I've tried avoiding "callback hell" and still cannot get this to work...
Any tips are very welcome!
Here is the current code:
var mysql = require('mysql');
var con = mysql.createConnection({
host: "10.0.1.103",
user: "badayaba",
password: "yadabuba",
database: "xeroetc"
});
(async function() {
let wewant1 = ["invoices", "accounts", "items", "organisations", "receipts", "taxRates", "users", "trackingCategories"];
function getmydata(sql, result, callback) {
var query = con.query(sql);
query.on('result', function(row) {
callback(null, row);
});
};
for (let i = 0; i < wewant1.length; i++) {
var sql = "select " + wewant1[i] + " from " + wewant1[i];
getmydata(sql, wewant1[i], function querydata(err, result) {
console.log(err || result);
return result;
});
};
con.end();
})();
20180910 22:00 GMT-6
Thanks Steven!
I think I got it with this:
const XeroClient = require('xero-node').AccountingAPIClient;
const XeroErrors = require('xero-node').XeroError;
var mysql = require('mysql');
const config = {
appType: "private",
consumerKey: "_____",
consumerSecret: "_____",
privateKeyPath: "../../../ssl/_____.pem"
};
var con = mysql.createConnection({
host: "_____",
user: "_____",
password: "_____",
database: "xeroetc"
});
(async function(){
let wewant1 = ["invoices","accounts","items","organisations","receipts","taxRates","users","trackingCategories"];
let xero = new XeroClient(config);
function getmydata(it, callback) {
var sql = "select "+it+" from "+it;
con.query(sql, function (err, result, fields) {
if (err) throw err;
callback(null,result);
});
};
const promises = wewant1.map(it => {
return new Promise((resolve, reject) => {
getmydata(it, function querydata(err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
});
})
});
Promise.all(promises)
.then(results => {
//results is a array of the resolved promises
invoices=results[0];
accounts=results[1];
items=results[2];
organisations=results[3];
receipts=results[4];
taxRates=results[5];
users=results[6];
trackingCategories=results[7];
console.log(invoices);
})
.catch(err => {})
.then(() => {
con.end();
})
})();
Map your array to promises, and then use Promise.all. This also solves your unstated problem of closing your connection too early.
var mysql = require('mysql');
var con = mysql.createConnection({
host: "10.0.1.103",
user: "badayaba",
password: "yadabuba",
database: "xeroetc"
});
let wewant1 = ["invoices", "accounts", "items", "organisations", "receipts", "taxRates", "users", "trackingCategories"];
function getmydata(sql, result, callback) {
var query = con.query(sql);
query.on('result', function(row) {
callback(null, row);
});
};
const promises = weweant1.map(it => {
return new Promise((resolve, reject) => {
getmydata(sql, it, function querydata(err, result) {
if (err) {
reject(err);
} else {
resolve(result);
}
});
})
});
Promise.all(promises)
.then(results => {
//results is a array of the resolved promises
})
.catch(err => {})
.then(() => {
// then after catch is a finally block
con.end();
})
Of course you can also use async/await and get rid of the then nesting. You can additionally promisify getmydata. All use the same principle though: Wait on an array of promises.
Using async/await
If getmydata returned a promise or was declared async, the following snippet would do, assuming it was in an async function. So much cleaner...
const promises = weweant1.map(it => getmydata(sql, it))
try {
const results = await Promise.all(promises)
} catch (e) {
// handle error
} finally {
con.end();
}