check if user in group ActiveDirectory.js node.js - javascript

In c# I would write something like this:
bool HasRole(string userName, string[] groupNames)
{
var ad = new ActiveDirectory();
return groupsNames.Any(groupName => ad.IsUserInGroup(userName, groupName);
}
and then just
if (HasRole("UserName", new[] {"group1", "group2"}))
//do something
in javascript it looks like all things are doing asynchronously, I've read about promises and so on, and tried this:
const ActiveDirectory = require('activedirectory2');
const Promise = require('promise');
const globals = require('./globals');
const activeDirectory = new ActiveDirectory(globals.AdConfig);
hasRole(msg, ...groupNames) {
if (groupNames == null || groupNames == undefined || groupNames.length == 0)
return false;
let promises = [];
groupNames.forEach(groupName => {
let promise = new Promise((resolve, reject) => {
activeDirectory.isUserMemberOf(msg.envelope.user.name, groupName, function (err, isMember) {
if (err) {
reject(err)
}
resolve(isMember);
});
});
promises.push(promise);
});
//I don't clearly understand how I can return promise result only or promise with the right result
let hasRole = false;
promises.forEach(promise => promise.done(result => {
if (result)
hasRole = result;
}));
return hasRole;
So how can write something like:
if (hasRole(msg, 'group1', 'group2'))
//do something...
I suppose I should return promise but how I can do it if i need to check multiple groups?
UPDATE
I wrapped the forEach loop in promise:
return new Promise((resolve, reject) => {
promises.forEach(promise => promise.done(result => {
if (result)
return resolve(result);
}));
and then:
hasRole(msg, 'group1', 'group2').done(result => {
if (result)
//do...
});
May there is another way?

Found a solution. Promises.all is what i needed.
Result code:
hasRole(msg, ...groupNames) {
let promises = [];
groupNames = groupNames.filter(x => x.trim().length > 0);
if (groupNames == undefined || groupNames.length == 0)
{
promises.push(new Promise.resolve(false));
return Promise.all(promises);
}
groupNames.forEach(groupName => {
let promise = new Promise((resolve, reject) => {
activeDirectory.isUserMemberOf(msg.envelope.user.name, groupName, function (err, isMember) {
if (err) {
reject(err)
}
resolve(isMember);
});
});
promises.push(promise);
});
return Promise.all(promises);
}

Related

how to get return value of promise

Here is a function to find mx records of a service and i need to save the one value(with the lowest priority) to make a request to it. How can I save and return this value?
const dns = require('dns');
const email = '...#gmail.com'
let res = email.split('#').pop();
function getMxRecords(domain) {
return new Promise(function(resolve, reject) {
dns.resolveMx(domain, function(err, addresses) {
if (err) {
//console.log(err, err.stack)
resolve(null);
} else {
//console.log(addresses);
let copy = [...addresses];
//console.log(copy);
let theone = copy.reduce((previous, current) => {
if (previous.priority < current.priority) {
return current;
}
return previous;
});
resolve(theone);
}
});
});
}
let a = getMxRecords(res);
console.log(a);
Yeah, so i need to export this module to make a request to it like below;
let socket = net.createConnection(25, request(email), () => {})
so for this my function should request me or array or object with only one value, when i'm trying it doesn't work, i always get this:
Promise { } //HERE IS RETURN FROM MY FUNCTION (WITH .THEN)
Error in socket connect ECONNREFUSED 127.0.0.1:25
A Promise is mostly an asynchronous call. It returns an Promise-Object that will resolve or reject the Promise. To access the result, you will call some functions:
function getMxRecords(domain) {
return new Promise(function(resolve, reject) {
dns.resolveMx(domain, function(err, addresses) {
if (err) {
//console.log(err, err.stack)
resolve(null);
} else {
//console.log(addresses);
let copy = [...addresses];
//console.log(copy);
let theone = copy.reduce((previous, current) => {
if (previous.priority < current.priority) {
return current;
}
return previous;
});
resolve(theone);
}
});
});
}
getMxRecords(res)
.then(yourResolveValueProvided => {
// Your code if the promise succeeded
})
.catch(error => {
// Your code if the promises reject() were called. error would be the provided parameter.
})

Problems with promises in JavaScript

The last line of code doesn't work and I don't know how to fix it. I understand that second "then" has to return resolve() but how can I realize it?
let getNumber = new Promise((resolve) => {
//API
EthereumNote.getAmountOfMyNotes(function(error, result) {
if (!error) {
let AmountOfMyNotes = Number(result)
resolve(AmountOfMyNotes)
console.log(result)
} else
console.error(error)
})
}).then(result => {
return new Promise((resolve) => {
for (let i = 0, p = Promise.resolve(); i < result; i++) {
p = p.then(_ => new Promise(resolve => {
//API
EthereumNote.getMyNote(i, function(error, result) {
if (!error) {
let text = String(result[0])
let noteID = Number(result[1])
console.log(text)
console.log(noteID)
resolve()
} else
console.error(error)
})
}));
}
})
}).then(() => console.log('Hi!')) // this one doesn't work
Avoid the Promise constructor antipattern! It's ok to make a new Promise to wrap EthereumNote.getMyNote, it's not ok to wrap the loop. You never resolve() that outer promise.
Instead, just return the promise chain you created in p:
let getNumber = new Promise((resolve) => {
//API
EthereumNote.getAmountOfMyNotes(function(error, result) {
if (error) reject(error);
else resolve(Number(result));
})
}).then(amountOfMyNotes => {
console.log(amountOfMyNotes);
var p = Promise.resolve();
for (let i = 0; i < amountOfMyNotes; i++) {
p = p.then(_ => new Promise((resolve, reject) => {
//API
EthereumNote.getMyNote(i, function(error, result) {
if (error) reject(error);
else resolve(result);
});
})).then(result => {
let text = String(result[0])
let noteID = Number(result[1])
console.log(text)
console.log(noteID))
});
}
return p;
}).then(() => {
console.log('Hi!'); // this one now works
}, err => {
console.error(err);
});

NodeJS, multiple if may return headers (and fails)

Updated with Promise example.
I'm running NodeJS and are having issues with multiple if-statements and return-statements.
I'm trying to use Promise at it might seem as a way to go.
This is my example code:
const express = require('express');
const app = express();
const pgPromise = require('pg-promise')();
const db = pgPromise(CONNECTION_STRING);
app.use((req, res) => {
var message = "";
promise1 = new Promise((resolve, reject) => {
message += "promise1";
if (false) {
reject(message);
}
});
promise2 = new Promise((resolve, reject) => {
if (true) {
db.one('SELECT 1')
.then(row => {
message += " promise2";
resolve(message);
})
.catch(err => {
message += " error";
reject(message);
});
}
});
var printResult = (results) => {console.log("Results = ", results, "message = ", message)}
Promise.all([promise1, promise2]).then(printResult);
return res.json({ message: message });
});
app.listen(3000);
It doesn't seem to wait for the Promise 2 to finish the database query.
How can I make sure the database query is done before return any statement?
The code execution doesn't stop on Promise.all, you need to move the return statement to the Promise.all callback, and return the Promise returned by Promise.all.
return Promise.all([promise1, promise2]).then(() => {
printResult();
return res.json({ message: message });
});
Since Node JS runs asynchronously it doesn't wait for input1, inpu2, input3 to finish before executing final line(return res.json({ error: false });).
You need to use Promise to handle the sequence. Find the code below.
let input1 = new Promise(function (resolve, reject) {
if (typeof req.body.input1 != "undefined") {
// do something
resolve('Success');
} else {
reject('Error');
}
});
let input2 = new Promise(function (resolve, reject) {
if (typeof req.body.input2 != "undefined") {
// do something
resolve('Success');
} else {
reject('Error');
}
});
let input3 = new Promise(function (resolve, reject) {
if (typeof req.body.input3 != "undefined") {
// do something
resolve('Success');
} else {
reject('Error');
}
});
input1.then((value) => {
return res.json({ error: true });
})
.catch((e) => {
input2.then((value) => {
return res.json({ error: true });
})
.catch((e) => {
input3.then((value) => {
return res.json({ error: true });
})
.catch((e) => {
return res.json({ error: false });
})
})
})
If you want to handle all inputs asynchronously, use promise.all().

How return a value after a forEach loop using Promises?

I need to know how to return a value after a forEach loop using Promises. In this moment, when I launch my main, I get :
[ Promise { <pending> }, Promise { <pending> } ]
(my sampleidlist contains only 2 records)
This is my code :
MongoClient.connect("mongodb://127.0.0.1/myproject", function(err, db) {
return db.collection('RUN').find({
"idRun": query.idRun
}).toArray()
.then((out) => {
var sampleidlist = out[0].SAMPLE_ID
var pazlist = []
// Promisearr is the array of promises where I try to push the promises
var Promisearr = []
// there is the function find_paz that return idPaz for every sampleId in sampleidlist
function find_paz(sampleid) {
// I return a new Promise for every sampleId
// I want to create an array of idPaz
return new Promise((resolve, reject) => {
db.collection('PATIENTS').find({
"SAMPLE_ID": sampleid
}).toArray()
.then((pazArr) => {
var singlepaz = []
singlepaz.push(pazArr[0].idPaz)
return singlepaz
})
.then((singlepaz) => {
pazlist.push(singlepaz)
})
})
}
// Here the forEach loop
sampleidlist.forEach(sampleid => {
Promisearr.push(
find_paz(sampleid)
)
})
Promise.resolve(Promisearr)
.then(Promise.all(Promisearr))
.then(value => {
// value return {promise<pending>}
// I want that value is the array of idPaz
console.log(value)
}).catch((err) => {
console.log('errored', err);
})
}).catch((err) => {
console.log('errored', err);
})
})
Any suggest?
Thank you very much :)
You have it mixed up between Promise.all and Promise.resolve. Here:
return db.collection('RUN').find({
"idRun": query.idRun
}).toArray()
.then((out) => {
var sampleidlist = out[0].SAMPLE_ID
var pazlist = []
var Promisearr = []
function find_paz(sampleid) {
return db.collection('PATIENTS').find({
"SAMPLE_ID": sampleid
}).toArray()
.then((pazArr) => {
var singlepaz = []
singlepaz.push(pazArr[0].idPaz)
return singlepaz
})
.then((singlepaz) => {
pazlist.push(singlepaz)
return;
})
})
}
Promise.all(sampleidlist.map(find_paz))
.then(values => {
//values is an array with all the promises resolved
//pazlist should have your data.
}).catch((err) => {
console.log('errored', err);
})
}).catch((err) => {
console.log('errored', err);
})
Give it a try, let me know if you need clarification or if it doesn't work.
You are using Promise.resolve() and Promise.all() the wrong way. You should just call Promise.all() then .then(), like this :
Promise.all(Promisearr).then(value =>
console.log(value)
)

waiting for many async functions execution

I have the promise function that execute async function in the loop few times for different data. I want to wait till all async functions will be executed and then resolve(), (or call callback function in non-promise function):
var readFiles = ()=>{
return new Promise((resolve,reject)=>{
var iterator = 0;
var contents = {};
for(let i in this.files){
iterator++;
let p = path.resolve(this.componentPath,this.files[i]);
fs.readFile(p,{encoding:'utf8'},(err,data)=>{
if(err){
reject(`Could not read ${this.files[i]} file.`);
} else {
contents[this.files[i]] = data;
iterator--;
if(!iterator) resolve(contents);
}
});
}
if(!iterator) resolve(contents); //in case of !this.files.length
});
};
I increase iterator on every loop repetition, then, in async function's callback decrease iterator and check if all async functions are done (iterator===0), if so - call resolve().
It works great, but seems not elegant and readable. Do you know any better way for this issue?
Following up the comment with some code and more detail!
Promise.all() takes an iterator, and waits for all promises to either resolve or reject. It will then return the results of all the promises. So instead of keeping track of when all promises resolve, we can create little promises and add them to an array. Then, use Promise.all() to wait for all of them to resolve.
const readFiles = () => {
const promises = [];
for(let i in files) {
const p = path.resolve(componentPath, files[i]);
promises.push(new Promise((resolve, reject) => {
fs.readFile(p, {encoding:'utf8'}, (err, data) => {
if(err) {
reject(`Could not read ${files[i]} file.`);
} else {
resolve(data);
}
});
}));
}
return Promise.all(promises);
};
const fileContents = readFiles().then(contents => {
console.log(contents)
})
.catch(err => console.error(err));
You only need push all the Promises into an array to then pass it as argument to Promise.all(arrayOfPromises)
try something like this:
var readFiles = () => {
var promises = [];
let contents = {};
var keys_files = Object.keys(this.files);
if (keys_files.length <= 0) {
var promise = new Promise((resolve, reject) => {
resolve(contents);
});
promises.push(promise);
}
keys_files.forEach((key) => {
var file = this.files[key];
var promise = new Promise((resolve, reject) => {
const currentPath = path.resolve(this.componentPath, file);
fs.readFile(p,{encoding:'utf8'},(err, data) => {
if (err) {
return reject(`Could not read ${file} file.`);
}
contents[file] = data;
resolve(contents)
});
});
});
return Promises.all(promises);
}
Then you should use the function like so:
// this will return a promise that contains an array of promises
var readAllFiles = readFiles();
// the then block only will execute if all promises were resolved if one of them were reject so all the process was rejected automatically
readAllFiles.then((promises) => {
promises.forEach((respond) => {
console.log(respond);
});
}).catch((error) => error);
If you don't care if one of the promises was rejected, maybe you should do the following
var readFiles = () => {
var promises = [];
let contents = {};
var keys_files = Object.keys(this.files);
if (keys_files.length <= 0) {
var promise = new Promise((resolve, reject) => {
resolve(contents);
});
promises.push(promise);
}
keys_files.forEach((key) => {
var file = this.files[key];
var promise = new Promise((resolve, reject) => {
const currentPath = path.resolve(this.componentPath, file);
fs.readFile(p,{encoding:'utf8'},(err, data) => {
// create an object with the information
let info = { completed: true };
if (err) {
info.completed = false;
info.error = err;
return resolve(info);
}
info.data = data;
contents[file] = info;
resolve(contents)
});
});
});
return Promises.all(promises);
}
Copied from comments:
Also - you might want to use fs-extra, a drop-in replacement for fs, but with promise support added.
Here's how that goes:
const fs = require('fs-extra');
var readFiles = ()=>{
let promises = files
.map(file => path.resolve(componentPath, file))
.map(path => fs.readFile(path));
return Promise.all(promises);
});
Nice and clean. You can then get contents like this:
readFiles()
.then(contents => { ... })
.catch(error => { ... });
This will fail on first error though (because that's what Promise.all does). If you want individual error handling, you can add another map line:
.map(promise => promise.catch(err => err));
Then you can filter the results:
let errors = contents.filter(content => content instanceof Error)
let successes = contents.filter(content => !(content instanceof Error))

Categories

Resources