I'm making an user management with the Amazon Web Service names Cognito.
It runs smoothly on local but it is not when I use it on a Wamp server.
I can not figure out why... maybe cause to asynchronous execution ?
I'm using $q and .then(function() { ... }); to wait for it's execution.
This is how I do in my controller :
$scope.validateForm = function() {
if (AuthService.getActifUser() == false) {
//clear local storage
$storage.remove('userData');
}
//getting the form attributes
var datafirstName = {
Name: 'custom:first_name',
Value: $scope.firstName
};
var dataLastName = {
Name: 'custom:last_name',
Value: $scope.lastName
};
var dataEmail = {
Name: 'email',
Value: $scope.email
};
var attributeFirstName = AuthService.setAttributes(datafirstName);
var attributeLastName = AuthService.setAttributes(dataLastName);
var attributeEmail = AuthService.setAttributes(dataEmail);
var attributeList = [];
attributeList.push(attributeFirstName);
attributeList.push(attributeLastName);
attributeList.push(attributeEmail);
// signing try
AuthService.signin($scope.username, $scope.password, attributeList)
.then(function(res) {
// save username in local storage
$storage.set('userData', $scope.username);
// go to the verification page
routeService.goToView('/users-confirmation');
}, function(res) {
console.log(res);
);
}
And in the AuthService Factory :
AuthService.signin = function(username, password, attributeList) {
var deferred = $q.defer();
userPool.signUp(username, password, attributeList, null, function(err, result) {
if (err) {
alert(err);
deferred.reject('registering failled.');
}
console.log('successfully registered.');
deferred.resolve('successfully registered.');
});
return deferred.promise;
};
Unfortunatelly the routeService.goToView() method is never called.
Hope someone know why ?
Could you please add a handler for the promise rejection to ensure that the promise is not being rejected?
It could be that your promise is being rejected and the error hidden. Also, where is invalidPassword being defined?
Related
I am trying to get an async intern test working using a separate module to do the request call. I am having an issue returning true once the test is done because I always get a timeout error, even though the request is successful, and the test runs to completion. After the test runs it just sits on the last page and times out. login_test.js is the test file, companyCreate is the request calling file that exists in an external module. I'm not quite sure what is happening to my test return call if I pass it into deferred.callback().
// login_test.js
define([
'intern!object',
'pages/loginpage',
'runtime/testConfig',
'intern/dojo/node!nconf',
'helpers/companyCreate',
'locators/loginpage',
'locators/companyselectionpage'
], function(registerSuite, LoginPage, conf, nconf, Company) {
var tests = {
name: 'Login test',
'Test': function() {
/* make a call to create a company
* param1: test function to run after we get response with login details
* param2: intern object so we can make it async
*/
Company.createCompany(function(response, testObj) {
testObj.timeout = 120000; //The default timeout is 30 seconds. Not enough
var region = nconf.get("region"); //Getting command line region value
var regionData = conf.get(region); //Fetching config data based on region
var loginId = regionData.LOGIN;
var password = regionData.PASSWORD;
var loginPage = new LoginPage(testObj.remote, regionData.DEFAULT_TIMEOUT);
var companySelectionPage = loginPage
.load(regionData.BASE_URL)
.loginIn(loginId, password);
var homePage = companySelectionPage
.doesCurrentURLContain('/companysel')
.isTitlePresent()
.selectCompany(CompanySelectionLocators.data);
return homePage
.doesCurrentURLContain('/homepage')
.getAccumulatedState();
}, this);
}
};
registerSuite(tests);
});
>
// companyCreate.js
define(function(require) {
var request = require('intern/dojo/request');
var Company = {
createCompany: function(callbackArg, testObj) {
// tell intern this is async
var deferred = testObj.async(120000);
// make post
request.post('https://internal.com/createcompany', {
query: {
version: ".0.1",
special: "true"
},
data: JSON.stringify({
userName: "Test",
password: "pass",
userEmail: "email#hi.com"
}),
headers: {
'Content-Type': "application/json"
}
}).then(function(response) {
// success, tell intern async is done, return test function to run and pass it the response
console.log(response);
return deferred.callback(callbackArg(response, testObj));
}, function(err) {
console.log(err);
}, function(evt) {
//console.log(evt);
});
}
};
return Company;
});
deferred.callback is intended to be used to wrap another callback that is executed at another time. It doesn’t resolve the underlying Promise, it returns a new function that, when invoked, resolves the Promise if the passed in callback function doesn’t throw an error. For example:
'Test': function () {
var dfd = this.async();
// this use of `dfd.callback`…
fs.readFile('foo.txt', dfd.callback(function (error, data) {
if (error) {
throw error;
}
assert.strictEqual(data, 'hello, world');
}));
// …is equivalent to this without it:
fs.readFile('foo.txt', function (error, data) {
if (error) {
dfd.reject(error);
return;
}
try {
assert.strictEqual(data, 'hello, world');
}
catch (error) {
dfd.reject(error);
return;
}
dfd.resolve();
}));
}
You should be using deferred.resolve, which resolves the promise to the value passed as the first argument. See the async tests documentation for more detailed information on each of these functions.
Working solution is below. I had no need for this.async. comapnyCreate.js returns the response and promise from the request. login_test.js runs the test after the promise is fulfilled. (still needs some error handling logic)
// login_test.js
define([
'intern!object',
'pages/loginpage',
'runtime/testConfig',
'intern/dojo/node!nconf',
'helpers/companyCreate',
'locators/loginpage',
'locators/companyselectionpage'
], function(registerSuite, LoginPage, conf, nconf, Company) {
var tests = {
name: 'Login test',
'Test': function() {
this.timeout = 60000;
var remote = this.remote;
return Company.createCompany().then(function(response) {
var region = nconf.get("region"); //Getting command line region value
var regionData = conf.get(region); //Fetching config data based on region
var loginId = regionData.LOGIN;
var password = regionData.PASSWORD;
var loginPage = new LoginPage(remote, regionData.DEFAULT_TIMEOUT);
var companySelectionPage = loginPage
.load(regionData.BASE_URL)
.loginIn(loginId, password);
var homePage = companySelectionPage
.doesCurrentURLContain('/companysel')
.isTitlePresent()
.selectCompany(CompanySelectionLocators.data);
return homePage
.doesCurrentURLContain('/homepage')
.getAccumulatedState();
});
}
};
registerSuite(tests);
});
// companyCreate.js
define(function(require) {
var request = require('intern/dojo/request');
var Company = {
createCompany: function() {
// make post
return request.post('https://internal.com/createcompany', {
query: {
version: ".0.1",
special: "true"
},
data: JSON.stringify({
userName: "Test",
password: "pass",
userEmail: "email#hi.com"
}),
headers: {
'Content-Type': "application/json"
}
});
}
};
return Company;
});
I have an App using Parse.com as a backend and an external site that acts as my payment gateway. Upon receiving the customer/subscription webhook data from Stripe I wish to lookup the users email so I can then run a Cloud Code function and change their user status to 'paid'
My webhook receiver is:
Parse.Cloud.define("update_user", function(request, response) {
var data = request.params["data"]
var customer = data.object.customer;
response.success'Working' + request);
});
And I am able to get an email back from stripe from the customer ID using:
Parse.Cloud.define("pay", function(request, response) {
Stripe.initialize(STRIPE_SECRET_KEY);
console.log(JSON.stringify(request.params));
Stripe.Customers.retrieve(
customerId, {
success:function(results) {
console.log(results["email"]);
// alert(results["email"]);
response.success(results);
},
error:function(error) {
response.error("Error:" +error);
}
}
);
});
I need help turning this into a complete function that is run on receipt of every webhook from Stripe. I am also struggling with options for fallback if this does not work for whatever reason.
EDIT
Taking parts of the first answer and I now have:
Parse.Cloud.define("update_user", function(request, response) {
Stripe.initialize(STRIPE_SECRET_KEY);
var data = request.params["data"]
var customerId = data.object.customer;
get_stripe_customer(customerId, 100).then(function(stripeResponse) {
response.success(stripeResponse);
}, function(error) {
response.error(error);
});
});
function get_stripe_customer (customerId) {
Stripe.initialize(STRIPE_SECRET_KEY);
return Stripe.Customers.retrieve(
customerId, {
success:function(results) {
console.log(results["email"]);
},
error:function(error) {
}
}
);
};
My knowledge is really falling down on the Promise side of things and also the callback (success:, error, request response) etc further reading would be appreciated.
This is now working
Out of interest I did this:
Parse.Cloud.define("update_user", function(request, response) {
var data = request.params["data"]
var customerId = data.object.customer;
get_stripe_customer(customerId, 100).then(function(stripeResponse) {
return set_user_status(username, stripeResponse);
}).then(function(username) {
response.success(username);
}, function(error) {
response.error(error);
});
});
function get_stripe_customer (customerId) {
Stripe.initialize(STRIPE_SECRET_KEY);
return Stripe.Customers.retrieve(
customerId, {
success:function(results) {
// console.log(results["email"]);
},
error:function(error) {
}
}
);
};
function set_user_status(stripeResponse) {
Parse.Cloud.useMasterKey();
var emailquery = new Parse.Query(Parse.User);
emailquery.equalTo("username", stripeResponse['email']); // find all the women
return emailquery.first({
success: function(results) {
alert('running set_user_status success');
var user = results;
user.set("tier", "paid");
user.save();
},
error:function(error) {
console.log('error finding user');
}
});
};
open to improvements...
EDIT - I (#danh) cleaned it up a bit. A few notes:
used promises throughout. much easier to read and handle errors
get_stripe_customer requires only one param (that 100 was my idea to charge $100)
set_user_status appears to need only user email as param, which apparently is in the stripeResponse
set_user_status returns a promise to save the user. that will be fulfilled with the user object, not the username
be sure you're clear on how to identify the user. stripe apparently provides email address, but in your user query (in set_user_status) you compare email to "username". some systems set username == email. make sure yours does or change that query.
Parse.Cloud.define("update_user", function(request, response) {
var data = request.params["data"]
var customerId = data.object.customer;
get_stripe_customer(customerId).then(function(stripeResponse) {
var email = stripeResponse.email;
return set_user_status(email);
}).then(function(user) {
response.success(user);
}, function(error) {
response.error(error);
});
});
function get_stripe_customer(customerId) {
Stripe.initialize(STRIPE_SECRET_KEY);
return Stripe.Customers.retrieve(customerId).then(function(results) {
// console.log(results["email"]);
return results;
});
};
function set_user_status(email) {
Parse.Cloud.useMasterKey();
var emailquery = new Parse.Query(Parse.User);
emailquery.equalTo("username", email); // find all the women
return emailquery.first().then(function(user) {
user.set("tier", "paid");
return user.save();
}, function(error) {
console.log('error finding user ' + error.message);
return error;
});
}
Did a quick skim of the docs pertaining to stripe, and it looks like the steps are: (1) make a stripe REST-api call from your client side to get a token, (2) pass that token to a cloud function, (3) call stripe from the parse cloud to finish paying. I understand that you'd like to include a (4) fourth step wherein the transaction is recorded in the data for the paying user.
From the client (assuming a JS client):
var token = // we've retrieved this from Stripe's REST api
Parse.Cloud.run("pay", { stripeToken: token }).then(function(result) {
// success
}, function(error) {
// error
});
On the server:
Parse.Cloud.define("pay", function(request, response) {
var user = request.user;
var stripeToken = request.params.stripeToken;
payStripeWithToken(stripeToken, 100).then(function(stripeResponse) {
return updateUserWithStripeResult(user, stripeResponse);
}).then(function(user) {
response.success(user);
}, function(error) {
response.error(error);
});
});
Now we need only to build promise-returning functions called payStripeWithToken and updateUserWithStripeResult.
// return a promise to pay stripe per their api
function payStripeWithToken(stripeToken, dollarAmt) {
Stripe.initialize(STRIPE_SECRET_KEY); // didn't see this in the docs, borrowed from your code
return Stripe.Charges.create({
amount: dollarAmt * 10, // expressed in cents
currency: "usd",
card: stripeToken //the token id should be sent from the client
});
// caller does the success/error handling
}
// return a promise to update user with stripeResponse
function updateUserWithStripeResult(user, stripeResponse) {
var transactionId = // dig this out of the stripeResponse if you need it
user.set("paid", true);
user.set("transactionId", transactionId);
return user.save();
}
Any ideas why this isn't working? It comes back with the success message but doesn't actually update anything.
I'm adding an FB user using Parse but since it doesn't have a func to add the username and email trying to do it this way. Any help much appreciated.
JS
Parse.Cloud.run("test", { objectId: "Q8XRUcL22N", name: "Rich", email: "rich#gmail.com"}, {
success: function(results) {
console.log(results);
},
error: function(error) {
console.log(error);
}
});
CLOUD CODE:
Parse.Cloud.define("test", function (request, response) {
Parse.Cloud.useMasterKey();
var uid;
var query = new Parse.Query("_User");
query.count({
success: function (results) {
uid = parseInt(results);
},
error: function () {
response.error("UID lookup failed");
}
});
var query = new Parse.Query(Parse.User);
query.equalTo("objectId", request.params.objectId);
query.first({
success: function (object) {
object.set("username", request.params.name);
object.set("email", request.params.email);
object.set("uid", uid);
var acl = new Parse.ACL();
acl.setPublicWriteAccess(false);
acl.setPublicReadAccess(false);
object.setACL(acl);
object.save();
response.success("Success Message");
},
error: function (error) {
response.error("Error Message");
}
});
});
Thanks
Calling success() or error() on the response halts whatever is underway at the time, including the save() on the user.
Also, it looks like you want to record in the user a count of users at the time the ACL is set. Getting the count must also be serialized with the other operations. (Also, please note that count is only good as an id "uid" to the extent the user count never goes down. What's wrong with the parse objects's id as an id?).
Most of the parse functions return promises, and using them is the only way to not go nuts trying to nest callbacks. So...
Parse.Cloud.define("test", function(request, response) {
Parse.Cloud.useMasterKey();
var uid;
var query = new Parse.Query(Parse.User);
query.count().then(function(count) {
uid = count;
return query.get(request.params.objectId);
}).then(function(object) {
object.set("username", request.params.name);
object.set("email", request.params.email);
object.set("uid", uid);
var acl = new Parse.ACL();
acl.setPublicWriteAccess(false);
acl.setPublicReadAccess(false);
object.setACL(acl);
return object.save();
}).then(function (object) {
response.success(object);
},function(error) {
response.error("Error Message");
});
});
I have LoginController and securityService.
This is LoginCtrl
// place the message if something goes wrong
$scope.authMsg = '';
$scope.login = function () {
$scope.authMsg = '';
var loginData = {email: $scope.account.email, password: $scope.account.password};
securityService.login(loginData);
};
This is securityService
login: function (logData) {
var _vm = this;
$http
.post('/api-token-auth/', logData)
.then(function (response) {
// assumes if ok, response is an object with some data, if not, a string with error
// customize according to your api
if (!response.data.token) {
_vm.authMsg = 'Incorrect credentials.';
} else {
$cookieStore.put('djangotoken', response.data.token);
$http.defaults.headers.common.Authorization = 'JWT ' + response.data.token;
$http.get('/api/account/restricted/').then(function (response) {
authService.loginConfirmed();
_vm.currentUser = response.data;
$rootScope.currentUser = response.data;
});
}
}, function (x) {
_vm.authMsg = 'Server Request Error';
});
},
This login is working fine but my problem is i don't know how can get the authMesg from service to controller because that is async. Everytime i get blank message in case of invalid login
you need to use promise service of angular to make you controller and service syn
login: function (logData) {
var _vm = this,d= $$q.defer();
$http
.post('/api-token-auth/', logData)
.then(function (response) {
// assumes if ok, response is an object with some data, if not, a string with error
// customize according to your api
if (!response.data.token) {
_vm.authMsg = 'Incorrect credentials.';
} else {
$cookieStore.put('djangotoken', response.data.token);
$http.defaults.headers.common.Authorization = 'JWT ' + response.data.token;
$http.get('/api/account/restricted/').then(function (response) {
authService.loginConfirmed();
_vm.currentUser = response.data;
$rootScope.currentUser = response.data;
});
}
d.resolve(vm.authMsg);
}, function (x) {
_vm.authMsg = 'Server Request Error';
d.reject(vm.authMsg);
});
},
In controller you need to resolve this promise
securityService.login(loginData).then(function(data){
consol.log(data); // get success data
},function(error){
consol.log(data); // get error message data
})
and inject $q in your service.
This will give you authMsg
securityService.login(loginData).authMsg
But follow #Vigneswaran Marimuthu comments, that is best practice.
I try to get data from an LDAP-Server via a Meteor server to the client.
But the LDAP-Request is asynchronous and the method returns false and not the result that is collected in the ldap.search function-call. So, how can i get the calls to the ldap synchronously or trigger an event on the client when the data is ready?
//defined on serverside
Meteor.methods({
searchPerson: function(account){
var data = null;
var LDAP = Npm.require('LDAP');
var ldap = new LDAP({uri: 'ldaps://ldap-server', version: 3});
var search_options = {
base: 'ou=xxx,dc=yyy,dc=zzz',
scope: '1',
filter: '(uid='+account+')',
attrs: 'surname, givenname, mail'
};
var bind_options = {
binddn: 'cn=aaa,ou=bbb,dc=ccc,dc=ddd',
password: 'password'
};
ldap.open(function(err) {
if (err) {
throw new Meteor.Error('Can not connect');
}
ldap.simpleBind(bind_options, function(err){
if (err){
throw new Meteor.Error('Can not bind');
}
ldap.search(search_options, function(err, data){
if (err){
throw new Meteor.Error('Error occured');
}
return data;
});
});
});
return false;
}
});
Thanks a lot.
torrofs
What you want is Meteor futures, as in this answer. This gist explains how.