I am using a custom auth challenge to get the otp as response, with below code I am able to get the OTP. But, instead of promise how can I use async/await to get the response from intiateAuth.
const params = {
AuthFlow: ".......",
ClientId: "*********",
AuthParameters: {
"USERNAME": req.userName,
}
};
return new Promise((resolve, reject) => {
new AWS.CognitoIdentityServiceProvider().initiateAuth(params, (err, data) => {
if (err) {
console.log("Error in adminInitiateAuth: %s", err.message);
reject(false);
} else {
const otpResponse: IOTPResponseDetails = {
session: data.Session,
userName: data.ChallengeParameters.USERNAME,
}
resolve(otpResponse);
}
});
});
}```
Create an async function. Use "await" inside a try/catch block to capture any errors.
const params = {
AuthFlow: ".......",
ClientId: "*********",
AuthParameters: {
"USERNAME": req.userName,
}
};
// Async function using await
const execute = async(parameters) => {
try {
const data = await new AWS.CognitoIdentityServiceProvider().initiateAuth(parameters);
const otpResponse: IOTPResponseDetails = {
session: data.Session,
userName: data.ChallengeParameters.USERNAME,
};
return otpResponse;
} catch (err) {
console.log("Error in adminInitiateAuth: %s", err.message);
throw new Error(err.message);
}
}
// Call async function with params as argument
await execute(params);
Related
I am trying to fetch the users using my VPN setup. So in the AWS SSO / AWS IAM Identity Center, I have a group called __ with 2 users. Both users have attribute information such as email, phone number, first name.. etc.
As I try to fetch the information, on lambda I use the below code.
const AWS = require("aws-sdk");
async function getUserInformation(){
const identityStore = new AWS.IdentityStore({
accessKeyId: process.env.accessKeyId,
secretAccessKey: process.env.secretAccessKey,
region: process.env.region,
});
let params = {
IdentityStoreId: process.env.identityStoreId
};
const userIdPromise = () => {
return new Promise((resolve, reject) => {
identityStore.listUsers(params, (err, data) => {
if (err) {
return reject(err);
}
return resolve(data.Users);
});
});
};
const userInfoPromise = (Users) => {
const usersInfo = [];
return new Promise((resolve, reject) => {
Users.map(({ UserId }) => {
let params = {
IdentityStoreId: process.env.identityStoreId,
UserId: UserId,
};
identityStore.describeUser(params, function (err, data) {
if (err) {
return reject(err);
}
usersInfo.push(data);
if (usersInfo.length == Users.length) {
return resolve(usersInfo);
}
});
});
});
};
const Users = await userIdPromise();
const usersInfo= await userInfoPromise(Users);
return usersInfo;
}
exports.handler = async (event) => {
try {
const users = await getUserInformation();
return users;
} catch (err) {
return err;
}
};
The output i get from this is the following response, but I was expecting a response as in the documentation .
Response
[
{
"UserName": "jakob-2",
"UserId": "a34498c2-4011-70bd-1a24-*"
},
{
"UserName": "JakobCI",
"UserId": "2334c812-6051-70cd-a983-*"
}
]
i hope you can help as i have now tried for 3 days to get the correct responce information
I'm trying to get data from my Firebase function, but it keeps returning a null response. It looks like I need to return a promise and return my data in that promise, but I can't seem to get it to work even though I think I'm doing that. I'm not the most familiar with Node.JS, so I might be returning the wrong things in the promise.
Here's my function code:
exports.tasksLists = functions.region('us-east1').https.onCall((data) => {
const userDoc = db.collection('users').doc(data.text);
return userDoc.get().then((doc) => {
if (!doc.exists) {
return "";
} else {
return doc.data().tasksKey;
}
}).then((tasksCreds) => {
const oauth2Client = new google.auth.OAuth2(
'444701140384-srcttdrg28geg598h65dkekad47u9a48.apps.googleusercontent.com',
'wNL4ZrBGYOnXUMvEcE7Z_Smo',
'https://collag-oauth-u5b2i5chyq-ue.a.run.app/classroomcallback'
);
oauth2Client.setCredentials({
refresh_token: tasksCreds.refresh_token,
access_token: tasksCreds.token
});
const service = google.tasks({ version: 'v1', auth: oauth2Client });
return service.tasklists.list({}, (err, res) => {
if (err) {
functions.logger.error(new Error(err));
return JSON.stringify(err);
}
const lists = res.data.items;
if (lists) {
functions.logger.info(lists);
return lists;
} else {
functions.logger.info('no lists');
return "No lists";
}
});
})
.catch((e) => {
functions.logger.error(new Error(e));
return JSON.stringify(e);
});;
});
I've also tried putting the OAuth and API request in the first .then() under else but that didn't work either.
Here's my frontend code to call the function and handle the data:
let tasksLists = fireApp.functions('us-east1').httpsCallable('tasksLists');
tasksLists({ text: currentUser.uid }).then(function (result) {
if (!result.data) {
console.log('no data');
}
let lists = result.data;
console.log(lists);
});
The console.log(lists) just outputs null.
The problem is that you're not returning a promise. You can use the Promise constructor, passing in the resolve/reject parameters and call any of those when your want to return the asynchronous result. Change your cloud function like so:
exports.tasksLists = functions.region('us-east1').https.onCall((data) => {
const userDoc = db.collection('users').doc(data.text);
return new Promise((resolve, reject) => {
userDoc.get().then((doc) => {
if (!doc.exists) {
return "";
} else {
return doc.data().tasksKey;
}
}).then((tasksCreds) => {
const oauth2Client = new google.auth.OAuth2(
'444701140384-srcttdrg28geg598h65dkekad47u9a48.apps.googleusercontent.com',
'wNL4ZrBGYOnXUMvEcE7Z_Smo',
'https://collag-oauth-u5b2i5chyq-ue.a.run.app/classroomcallback'
);
oauth2Client.setCredentials({
refresh_token: tasksCreds.refresh_token,
access_token: tasksCreds.token
});
const service = google.tasks({ version: 'v1', auth: oauth2Client });
service.tasklists.list({}, (err, res) => {
if (err) {
functions.logger.error(new Error(err));
// return JSON.stringify(err);
reject(err);
}
const lists = res.data.items;
if (lists) {
functions.logger.info(lists);
resolve(lists);
// return lists;
} else {
functions.logger.info('no lists');
resolve("No lists")
// return "No lists";
}
});
})
.catch((e) => {
functions.logger.error(new Error(e));
reject(e);
// return JSON.stringify(e);
});
})
});
I am trying to write an async lambda function which is calling a function for sign up a user in cognito.
my problem is that in my lambda function, it is not waiting for the result and finish the execution. would you mind check what is my issue? I am new to rxjs. please help me.
mylambda function
exports.handler = async (event, context) => {
//poolData and params will fetch from event
let source = await signup(poolData, params);
console.log(source);
});
my signup function
function signup(poolData, body) {
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
const { username, password, attributes } = body;
const attributesList = [];
if (Array.isArray(attributes)) {
attributesList.push(
...attributes.map(item => new AmazonCognitoIdentity.CognitoUserAttribute(item))
);
}
let source = Observable.create(observer => {
let output = (err, res) => {
if (err)
{
observer.error(err);
}
else
{
const cognitoUser = res.user;
const data = {
username: cognitoUser.getUsername(),
};
observer.next(data);
}
observer.complete();
}
userPool.signUp(username, password, attributesList, null, output);
});
let respond;
let subscriber = {
next(value) {
console.log('Subscriber - next: ', value);
respond = {
'statusCode': 200,
'body': JSON.stringify({
"username": value.username,
})
}
}, error(err) {
console.log('Subscriber - err: ', err);
respond = err;
},
complete() {
console.log('Subscriber - complete');
return response;
}
};
source.subscribe(subscriber);
}
module.exports = signup;
This behavior is totally normal.
So first thing first, an observable is not a promise which means you are not able to await a response with the await keyword, also I don't see anything to be returned from the signup function, which will probably lead to undefined to be logged anyways.
So how to fix that, one way to fix this issue is to use toPromise() which will turn your observable into a promise which then can be awaited wherever needed.
The other way (which is the rxjs way) will be to return from the signup function the observable and inside your handler function to subscribe for the response.
let subscriber = {
next(value) {
console.log('Subscriber - next: ', value);
respond = {
'statusCode': 200,
'body': JSON.stringify({
"username": value.username,
})
}
}, error(err) {
console.log('Subscriber - err: ', err);
respond = err;
},
complete() {
console.log('Subscriber - complete');
return response;
}
};
exports.handler = (event, context) => {
//poolData and params will fetch from event
signup(poolData, params).subscribe(subscriber);
})
function getUserByStudentId(NIM) {
db.query('SELECT * FROM data_admin WHERE id_mahasiswa = ?', [NIM], async (err, result) => {
if (!result) {
return null
} else {
var data = await {
id: result[0].id_Admin,
email: result[0].email,
jabatan: result[0].jabatan,
password: result[0].password,
id_mahasiswa: result[0].id_mahasiswa,
id_Acara: result[0].id_Acara,
id_Organisasi: result[0].id_Organisasi
}
console.log(data) // there is a value here
return data
}
})
}
console.log(getUserByStudentId('1301194051')) // undefined returned
I'm a student and start learning nodejs. Would you explain to me, why my function returning undefined
console.log(getUserByStudentId('1301194051')) // undefined
but when I console.log on the function I got returned value
I'll promisify the function for you:
function getUserByStudentId(NIM) {
return new Promise(function(resolve, reject) => {
db.query('SELECT * FROM data_admin WHERE id_mahasiswa = ?', [NIM], (err, result) => {
if (!result) {
resolve(null);
} else {
var data = {
id: result[0].id_Admin,
email: result[0].email,
jabatan: result[0].jabatan,
password: result[0].password,
id_mahasiswa: result[0].id_mahasiswa,
id_Acara: result[0].id_Acara,
id_Organisasi: result[0].id_Organisasi
}
console.log(data) // there is a value here
resolve(data);
}
});
});
}
If you're going to use this function in global scope, use then:
getUserByStudentId('1301194051').then(result => {
console.log(result);
});
If you want to use this function inside an async function, you can await the result:
async function doSomethingWithUser(NIM) {
const user = await getUserByStudentId(NIM);
}
For example, if you're using express:
app.get('/user/:id', async (res, req) => {
const NIM = req.param.id;
const user = await getUserByStudentId(NIM);
res.json({ user });
});
I'm trying to develop an API post, in middle execution I have validation such as check name already in use or not. I set error handler callback, it successfully send response 'Already registered', but when I checked to CLI, it show error
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
I dont know whats wrong, I use this error handler in the past and it seems look ok.
Here is my code in router:
createUserAccount: async function (req, res) {
const programData = req.body;
try {
await service.create(programData, function (code, err, result) {
if (err) {
if(code === 409){
res.status(HTTPSTATUS.CONFLICT).send(err.message);
} else {
res.status(HTTPSTATUS.BAD_REQUEST).send(err.message);
}
} else {
res.status(HTTPSTATUS.CREATED).json(result);
}
})
} catch (e) {
console.log(e)
res.status(HTTPSTATUS.BAD_REQUEST).json("Failed.");
}
Here is my function in my service:
const config = require('#configs/config.json')
const sequelize = require('sequelize');
const SEQUELIZE = new sequelize(config[env]);
module.exports = {
createAccount: async (name, password, callback) => {
try {
let check,
institution_id;
const checkName = await Profile.count(
{
where: {
name: name
}
}
);
//result checkName = 1
if(checkName > 0){
//then successfully execute this condition and
return callback(409, 'Already registered.', null);
//this show in console ----> POST /API/v1/user/profile 409 616.152 ms - 31
}
await Login.create({
username: email,
password: password
}).then(resLogin => {
const response = {
id: resLogin.id,
}
callback(201, null, response);
}).catch( error => {
callback(400, error, null);
})
} catch (e) {
callback(400, e, null);
}
},
create: async (payload, callback) => {
let loginID = null;
let {
profile,
address
} = payload;
let {
name,
email,
password
} = profile;
try {
await module.exports.createAccount(name, password, function (code, error, result) {
if(error){
const res = {message: error};
//what I need is the execution is end in here
return callback(code, res, null);
}
loginID = result.id;
});
//but the fact is it still execute this whole function if got callback error from createAccount()
let transaction = await SEQUELIZE.transaction();
await Address.create(address, {transaction})
.then( async resAddress => {
await transaction.commit();
return callback(201, null, resProfile);
}).catch(async e => {
return callback(400, e, null);
})
} catch (e) {
console.log(e);
callback(e, null);
}
};