Can't get a Lambda function to send back information - ios

I just got my first Lambda function written, but it does not work at this point.
I tried a number of variations in the code; partly following what I could think of and partly following what I could come across on the net; but all failed.
I want the Lambda function to listUsers in a UserPool and get an email for a given sub passed as parameter.
Here is the Swift function making the call to the Lambda function:
func getLambdaInfo() {
let lambdaInvoker = AWSLambdaInvoker.default(),
jsonObject:[String: Any] = ["sub" : "MY-USER-SUB"]
lambdaInvoker.invokeFunction("myLambdaFunc", jsonObject: jsonObject)
.continueWith(block: {
(task:AWSTask<AnyObject>) -> Any? in
if( task.error != nil) {
print("Error: \(task.error!)")
return nil
}
print("\(#function) ---- WE ARE HERE!!!!")
// Handle response in task.result:
if let JSONDictionary = task.result as? NSDictionary {
print("Result: \(JSONDictionary)")
}
return nil
})
}
Here is the Lambda function:
var AWS = require('aws-sdk/dist/aws-sdk-react-native');
exports.handler = async (event,context) => {
var params = {
UserPoolId: 'MY-POOL-ID',
AttributesToGet: ['email'],
Limit: '2'
};
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
cognitoidentityserviceprovider.listUsers(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
// How can I get this data sent in the response is probably the issue ??
});
const response = {
inBound: event.sub,
statusCode: 200,
body: JSON.stringify('Hello from Lambda!')
};
return response;
}
Here is what can be seen in the Xcode debugging console:
getLambdaInfo() ---- WE ARE HERE!!!!
Result: {
body = "\"Hello from Lambda!\"";
inBound = "MY-USER-SUB";
statusCode = 200;
}
I hope someone with more AWSLambda than me will be able to give me some hints concerning the changes I need to make in my code to get the result (email address) I want (into my Swift getLambdaInfo()).

You need to move your return statement in the callback of listUsers:
cognitoidentityserviceprovider.listUsers(params, function(err, data) {
if (err) {
console.log(err, err.stack); // an error occurred
// return a 500 error ?
}
else {
console.log(data);
const response = {
inBound: event.sub,
statusCode: 200,
body: JSON.stringify(data)
}
return response;
}
});
Since you're using the async pattern you can also do:
try {
const data = await cognitoidentityserviceprovider.listUsers(params).promise() // note the await and .promise() here
const response = {
inBound: event.sub,
statusCode: 200,
body: JSON.stringify(data)
}
return response;
} catch (err) {
// do something with err
}
Otherwise your Lambda function returns before your callback gets executed (async nature of JavaScript).

Related

getting current result from method inside another method

am trying to call a method which calls another method .. and depending on that method result i will continue with my method .. something like this:
void submit() async{
if (login) {
....
bool result = await Login("966" + phone, _data.code);
if (result) {
successpage();
} else {
.....
}
and login:
bool Login(String phone, String SMScode) {
http.post(baseUrl + loginURL + "?phone=" + phone + "&smsVerificationCode="+ SMScode,
headers: {
'content-type': 'application/json'
}).then((response) {
final jsonResponse = json.decode(Utf8Codec().decode(response.bodyBytes));
print("LOGIN: " + jsonResponse.toString());
Map decoded = json.decode(response.body);
print(decoded['success']);
if (decoded['success']) {
globals.token = decoded['token'];
globals.login = true;
}else{
globals.login = false;
}
});
return globals.login;
}
but this doesn't work and doesn't give me the result of the last bool i need .. how to solve this?
The asynchronous handling is incorrect in your program. Basically your Login function returns without waiting the http post.
The following update should work.
Future<bool> Login(String phone, String SMScode) async {
final response = await http.post('$baseUrl$loginURL?phone=$phone&smsVerificationCode=$SMScode',
headers: {'content-type': 'application/json'});
final jsonResponse = json.decode(Utf8Codec().decode(response.bodyBytes));
print("LOGIN: " + jsonResponse.toString());
Map decoded = json.decode(response.body);
print(decoded['success']);
if (decoded['success']) {
globals.token = decoded['token'];
globals.login = true;
} else {
globals.login = false;
}
return globals.login;
}

Content.once is not a function

I try to push a file to the IPFS, and I have converted to the Buffer. I got this error " content.once is not a function".
I am using this library in node.
var Buffer = require('buffer/').Buffer;
const doc = new jsPDF();
doc.fromHTML('test',10,10);
var covnertedBuffer = Buffer.from(doc.output('arraybuffer');
Then, I take the convertedBuffer and pass it to the IPFS api.
Any idea?
Updated test:
I have successfully pushed a file to the IPFS via the API with this code below.
const filename = '/home/administrator/Downloads/5HP8LWKHLV.pdf';
this.ipfsApi = ipfsApi('localhost', '5001');
let readablestream = fs.createReadStream(filename);
readablestream.on('readable', () => {
let result = readablestream.read();
console.log(result);
if (result) {
this.ipfsApi.files.add(result, function(err, files) {
if (err) {
res.json('err');
console.log(err);
}
res.json(files);
});
}
});
But, when I get the arrayBuffer from the doc.output and convert to the Buffer object and push to the IPFS and it failed. Please see below.
var _buffer = Buffer.from(req.buffer);
console.log('Converted to buffer:' + _buffer);
this.ipfsApi = ipfsApi('localhost', '5001');
this.ipfsApi.files.add(_buffer, function(err, files) {
if (!err) {
res.status(500);
console.log(err);
} else {
res.json(files);
res.status(200);
}
});
Thank you
Adding Buffer.from(your_buffer) to your buffer before doing ipfs push works.
ipfs.files.add(Buffer.from(put_your_buffer_here), (error, result) => {
if(error) {
console.error(error)
return
}
console.log("upload is successful");
});

Null while returning a Future in Dart

I have two classes, a user_api_manager and a base_api_manager. From user_api_manager i call the get method of base_api_manager which performs an http get request and returns a Future<String>. The getrequest is performed but i am not pass the result to my user_api_manager class. The callback result is always null.
This is my user_api_manager.dart
static Future<Map<String,dynamic>> forgotPasswordAPI(String email) async{
String url = Constants.BASE_URL + Constants.FORGOT_PASSWORD_URL + email;
await BaseApiManager.get(url: url).then((val) {
var response = JSON.decode(val);
var status = response['status'];
String message = '';
print(response);
switch (response['status']) {
case Constants.SUCCESS:
message = Constants.SUCCESS_RESPONSE;
break;
case Constants.SERVER_ERROR:
message = Constants.SERVER_ERROR_MESSAGE;
break;
case Constants.UNAUTHORISED:
message = Constants.UNAUTHORISED_MESSAGE;
break;
}
return {'status':status,'message':message};
});
}
and here is my base_api_manager.dart
static Future<String> get({url : String,
parameters : Map ,
headers: Map }) async {
var client = new http.Client();
Map<String,dynamic> resultJSON;
final c = new Completer();
await client.get(url).then((response) { //response is always null
resultJSON = {
'status' : response.statusCode,
'body' : JSON.decode(response.body)
};
c.complete(resultJSON.toString());
return c.future;
});
}
How to solve this issue?
Move the return c.future outside of the response processing, i.e you want to return this from your get otherwise you will return null.
You can simplify the code. That should make it easier to locate the problem
static Future<String> get({url : String, parameters : Map, headers: Map }) async {
var client = new http.Client();
final response = await client.get(url);
print(response.body);
var resultJSON = {
'status' : response.statusCode,
'body' : JSON.decode(response.body)
};
return resultJSON.toString()
}
What does that code print?

Multiple login windows/keeps re-prompting for username/password on acquireToken()

Every time I make a call to acquireToken, it keeps launching the AAD login window and prompts me for a username/password, even though I've already authenticated successfully and consumed an access token to make API calls.
Here is my code
Step 1. Call the loadData function from controller
loadData = (): Rx.IPromise<Array<UserResult>> => {
var url = this.xxxApiUrl;
return Http.get<Array<UserResult>>(this._$http, url);
};
Step -2
export function get<TResult>(http: ng.IHttpService, url: string,
ignoreLoadingBar: boolean = false, retryCount = 0): Rx.IPromise<TResult> {
var req: any = {};
if (ignoreLoadingBar) {
req.ignoreLoadingBar = ignoreLoadingBar;
}
let resObservable = Rx.Observable.create(subscriber => {
acquireToken(url, (message, token) => {
req.headers.Authorization = `Bearer ${token}`;
http.get(url, req)
.then(res => {
subscriber.onNext(res.data);
subscriber.onCompleted();
}, (err) => { alert(JSON.stringify(err)); });
});
});
return resObservable.toPromise();
}
function acquireToken(apiUrl: string, callback) {
let innerCallback = (res) => callback('', res.accessToken);
let xConfig= JSON.parse(<any>sessionStorage.getItem('xConfig'));
window.AuthenticationContext = new
window.Microsoft.ADAL.AuthenticationContext
(xConfig.common.azure.authorityTenant);
window.AuthenticationContext.tokenCache.readItems().then(items => {
if (items.length > 0) {
let authority = items[0].authority;
window.AuthenticationContext = new
window.Microsoft.ADAL.AuthenticationContext(authority);
}
let resourceUri = getResourceUri(xConfig, apiUrl);
window.AuthenticationContext.acquireTokenSilentAsync(resourceUri,
xConfig.common.azure.clientId, xConfig.common.azure.redirectUri)
.then(innerCallback, (err) => {
window.AuthenticationContext.acquireTokenAsync(resourceUri,
xConfig.common.azure.clientId, xConfig.common.azure.redirectUri)
.then(innerCallback);
});
});
}
Looking at your code, it looks like that you are using acquireTokenSilentAsync using the common endpoint, this is not supported. Please make sure to use your tenant Id or name (like tenant.onmicrosoft.com) instead of common when using acquireTokenSilentAsync
For more information about the common endpoint please see here

Store access_token in the AsyncStorage

After user enters ID and password, I am passing access_token from Rails.
I am using
itzikbenh/Rails-React-Auth and
itzikbenh/React-Native-on-Rails as reference.
But I am unable to save the access_token. Here is the code:
let res = await response.text();
if (response.status >= 200 && response.status < 300) {
//Handle success
let accessToken = res;
console.log(accessToken);
//On success we will store the access_token in the AsyncStorage
this.storeToken(accessToken);
//this.redirect('home');
alert(ACCESS_TOKEN )
} else {
//Handle error
let error = res;
throw error;
}
You can use AsyncStorage.setItem to store single items:
import { ... AsyncStorage } from 'react-native'
try {
await AsyncStorage.setItem('access_token', access_token);
} catch (error) { // Error saving data }
Then to retrieve it use AsyncStorage.getItem:
try {
const value = await AsyncStorage.getItem('access_token');
if (value !== null) console.log(value)
} catch (error) { // Error retrieving data }
For storing and retrieving multiple items you can see AsyncStorage.multiSet and AsyncStorage.multiGet.

Resources