Introduction
OK, what I have is a app built in Node and Angular. I pass A users email to my backed using a post in Angular, from the backed the order in the backed is:
Get the email
Get API key
Post email and API key to API
I do this by posting email to backed then using node and express get email use promise resolve (first function) to pass the email to my third function as well as the API key retrieved from the second function.
What I need
Angular post to back end Node
Run first function, If first function has retrieved the email then run function 2. if not correct then pass information to the first post (Angular) to display message.
Run second function, if true run function 3
Finally run post with data collected from function 1 and 2, if post correctly pass 200 code to first function or pass to angular post.
Needed
Verification on the front end (Angular) on each step (function 1, 2 and 3 in Node) they can be response code so that I may print a different message depending on response code
Objective
A user post email on front end, then depending on if the email was accepted on the API let the user know, This is where different messages or redirects come in to play depending if it was a wrong or right email.
My Code
Angular side
This is where the first post to the Node back end happens, would be nice if this could get different response request depending on the results on the back-end.
var firstFunction = function () {
return new Promise(function (resolve) {
setTimeout(function () {
app.post('/back-end/controller', function (req, res) {
console.log(req.body);
var login = req.body.LoginEmail;
res.send(login);
resolve({
data_login_email: login
});
});
console.error("First done");
}, 2000);
});
};
Node side (all in controler.js)
First function
I would like this to trigger function 2 if success if not send a response code back to the Angular request.
var firstFunction = function () {
return new Promise(function (resolve) {
setTimeout(function () {
app.post('/back-end/controller', function (req, res) {
console.log(req.body);
var login = req.body.LoginEmail;
//Promise.all([firstFunction(), secondFunction()]) .then(thirdFunction);
//res.send(login);
resolve({
data_login_email: login
});
});
console.error("First done");
}, 2000);
});
};
Second function
This function gets API key, if This function is successful trigger function three.
var secondFunction = function () {
return new Promise(function (resolve) {
setTimeout(function () {
nodePardot.PardotAPI({
userKey: userkey,
email: emailAdmin,
password: password,
DEBUG: false
}, function (err, client) {
if (err) {
// Authentication failed
console.error("Authentication Failed", err);
} else {
// Authentication successful
var api_key = client.apiKey;
console.log("Authentication successful !", api_key);
resolve({data_api: api_key});
}
});
console.error("Second done");
}, 2000);
});
};
Third Function
If second function passes then this function should run using the email from the first and the API key from the second, If success then pass pass success back to first function to pass give 200 success to the angular side, or directly send a request response to Angular, If fail then again let the front end know.
function thirdFunction(result) {
return new Promise(function () {
setTimeout(function () {
var headers = {
'User-Agent': 'Super Agent/0.0.1',
'Content-Type': 'application/x-www-form-urlencoded'
};
// Configure the request
var api = result[1].data_api;
var login_email = result[0].data_login_email;
var options = {
url: 'https://pi.pardot.com/api/prospect/version/4/do/read',
method: 'POST',
headers: headers,
form: {
'email': login_email,
'user_key': userkey,
'api_key': api
},
json: true // Automatically stringifies the body to JSON
};
// Start the request
rp(options)
.then(function (parsedBody) {
console.info(login_email, "Is a user, login pass!");
// router.redirect('/login'); // main page url
// res.send.status(200);
})
.catch(function (err) {
console.error("fail no such user");
// res.status(400).send()
});
console.error("Third done");
}, 3000);
}
);
}
Promise.all([firstFunction(), secondFunction()]) .then(thirdFunction);
If anyone knows how to do this please can you help, this is the last part of my app i need to get working, Thanks.
Summery
In summery I would like different response codes Angular side depending on where and when the function got to on backed or if it passed all three functions.
Eg:
request code for fails to post to backed
Fails to get API key on function 2
Fails to send email to API on third function
Email not present on API
Email present on API and all pass, Your In !!
UPDATE
I found I can pass a message back to my Angular post using the following, but how can I make this message different depending on what function has run ?
var firstFunction = function () {
return new Promise(function (resolve) {
setTimeout(function () {
app.post('/back-end/controller', function (req, res) {
console.log(req.body);
// res.status(500).send({ error: "boo:(" });
res.send('hello world');
var login = req.body.LoginEmail;
res.send(login);
resolve({
data_login_email: login
});
});
console.error("First done");
}, 2000);
});
};
I solved this by merging 2 function into one (the retrieve function and post) then i changed the promise chain
var firstFunction = function () {
return new Promise(function (resolve) {
setTimeout(function () {
nodePardot.PardotAPI({
userKey: userkey,
email: emailAdmin,
password: password,
DEBUG: false
}, function (err, client) {
if (err) {
// Authentication failed
console.error("Authentication Failed", err);
} else {
// Authentication successful
var api_key = client.apiKey;
console.log("Success your API key is", api_key);
resolve({data_api: api_key});
}
});
}, 2000);
});
};
var secondFunction = function (result) {
return new Promise(function () {
setTimeout(function () {
app.post('/back-end/controller', function (req, res) {
console.log(req.body);
var login = req.body.LoginEmail;
var api = result[0].data_api;
var headers = {
'User-Agent': 'Super Agent/0.0.1',
'Content-Type': 'application/x-www-form-urlencoded'
};
var options = {
url: 'https://pi.pardot.com/api/prospect/version/4/do/read',
method: 'POST',
headers: headers,
form: {
'email': login,
'user_key': userkey,
'api_key': api
},
json: true // Automatically stringifies the body to JSON
};
if (login.length !== 0) { // maybe use node email validation ?
console.log("Email Accepted, Next posting to API.......");
rp(options)
.then(function (parsedBody) {
console.info(login, "Is a user, login pass!");
res.status(200).send({ user: login });
})
.catch(function (err) {
console.error("fail no such user");
res.status(400).send('fail to login');
});
} else {
console.log("Failed to get email from front end");
res.status(404).send('Incorrect length');
}
});
});
});
};
Promise.all([firstFunction()]).then(secondFunction);
Related
Im writing an application which connects to a 3rd party api.
The api uses a auth token system so i have an async node js function which first requests the token and then uses that token to retrieve some data.
The problem is that when the data changes the angualr $scope wont update so the page will show the same data even if an error is thrown in the node js api call.
A little run through the code.
get-salesLead-data.js Has a Async waterfall function which firsts calls the 3rd party rest api using http PUT and returns an auth token. This token is then passed into the second function of the Async water which is then used to make a http GET request to get the sales lead data.
Here is the Node Async api call.
**get-saleLead-data.js**
// app/get-SalesLead-data.js
// modules =================================================
var http = require('http');
var express = require('express')
var async = require('async');
module.exports = function(app) {
Using async to preform async api calls and passing data between them
async.waterfall([
// First function is requesting the auth token
requestToken = function(callback) {
var options = {
"host": "********",
"path": '************'
"method": "PUT",
"headers": {
"Content-Type": "application/json",
}
};
var login = JSON.stringify({
"username": "********",
"password": "********",
"client_ip_address": "********"
});
var req = http.request(options, function(res) {
res.on('data', function(body) {
var body = JSON.parse(body);
var token = body.token;
console.log(token);
callback(null, token);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write(login);
req.end();
},
// Second function is using the auth token receieved from the first function to get sales lead dat
getData = function(arg1, callback) {
// Geting the sales id from the url and using it in the api request.
app.get('/', function(req, res) {
app.set('salesLeadId', req.query.id);
var token = arg1;
var auth = 'Basic ' + new Buffer('********' + ':' + token).toString('base64');
var path = '****************' + app.get('salesLeadId');
var options = {
"host": "********",
"path": path,
"method": "GET",
"headers": {
"Content-Type": "application/json",
"Authorization": auth
}
};
var data = '';
// Assinging response data to to data
var req = http.request(options, function(res) {
res.on('data', function(chunk) {
data += chunk;
});
// Creating sales lead api so the front end can make requests
res.on('end', function(res) {
var body = JSON.parse(data);
console.log(body);
app.get('/api/salesLead', function(req, res) {
return res.json(body);
$scope.$apply();
});
})
});
req.on('error', function() {
alert('error');
});
res.sendFile('index.html', {
root: '../vpbx/public/views'
});
req.end();
});
}
], function(err, result) {
});
};
Below is the service which accesses /api/salesLead
Creating a function which calls the backend usinga http GET request. This then returns the sales lead data.
**salesLeadService.js**
angular.module('SalesLeadService', []).service('SalesLeadService', function($http, $location, $rootScope) {
var urlBase = '/api/salesLead'
this.getSalesLead = function (data) {
return $http.get(urlBase, data)
};
});
below is the offer controller. This calls the service above and assigns the data to the $scope.salesLead.
**offer.js**
// Form controller
// =============================================================================
angular.module('offerController', []).controller('offerController', function($scope, $http, SalesLeadService, $timeout) {
// GETTING THE DATE-TIME STAMP
$scope.getDate = new Date();
$scope.date = Date();
// CALLING THE FUNCTION FROM THE SALES LEAD SERVICE
SalesLeadService.getSalesLead()
.then(function(response) {
$scope.salesLead = response.data;
$scope.$applyAsync();
});
});
Just a note that i have tried using $scope.$apply but havnt had any luck.
Any help is appreciated
Thanks
Try with object like this way
$scope.object = {salesLead : ''};
$scope.object.salesLead = response.data;
HTML
use {{object.salesLead}}
I think it will work for you
offer.js
angular.module('offerController', []).controller('offerController', function($scope, $http, SalesLeadService, $timeout) {
// GETTING THE DATE-TIME STAMP
$scope.getDate = new Date();
$scope.date = Date();
// CALLING THE FUNCTION FROM THE SALES LEAD SERVICE
$scope.object = {salesLead:''};
SalesLeadService.getSalesLead()
.then(function(response) {
$scope.object.salesLead = response.data;
$scope.$applyAsync();
});
});
I found the issue wasnt to do with the front end but my backend.
The issue was that i had a nested route.
To fix the issue i completely rewrote my routes.
I am trying to make GET request with node request module. I am making request to the coursera api. As the api is using CORS. Therefore I have to make server side requests.
But the thing is how to use this data in index.html to dynamically fill data.
As here I am getting the whole data to the file. Is there any way to give this data to the Angular controller.
In brief, I want to use data from coursera api inside my angular app. I have used client side so know less about server side.
var request = require("request");
var fs = require("fs");
request("https://api.coursera.org/api/courses.v1").pipe(fs.createWriteStream("data.json"));
There are two ways you can get the data into index.html:
1) Use Jade (Pug) Render:
var COURSERA_DATA = null;
router.get('/', function (req, res) {
if (!COURSERA_DATA) {
request("https://api.coursera.org/api/courses.v1",function(err,res,body) {
COURSERA_DATA = body; /* verify first */
res.render('index', {data: COURSERA_DATA});
});
} else {
res.render('index', {data: COURSERA_DATA});
}
});
and then in index.html:
script(text/javascript).
var theDATA = !{JSON.stringify(data)}; // inserted by jade
and finally in angular1
app.controller('AnyController',function() {
var vm = this;
vm.data = theDATA;
});
2) Client request to URL which is proxied to coursera's API
router.get('/coursera', function (req, res) {
request("https://api.coursera.org/api/courses.v1").pipe(res);
}
Aaron
Why the problem to consume data right in Angular? Something like:
app.controller('controller', function($scope, $http) {
$scope.getCursera = function() {
$http({
url: "https://api.coursera.org/api/courses.v1",
method: "GET",
contentType: "application/json"
}).success(function(data) {
$scope.jsonResponse = data;
}).error(function(err) {
console.log(err);
});
};
});
If Coursera allow Cross Domain this it's works. The JSON response will be setted at the scope, such that you be able to show in view or do anything.
You can try to implement a simple api to send the response back to your controller like this..
In the server side .. (Demo)
var request = require('request');
router.get('/coursera', function (req, res,next) {
request.get(
'https://api.coursera.org/api/courses.v1',
{ json: { key: 'value' } },
function (error, response, body) {
if (!error && response.statusCode == 200) {
res.send(body); //response from coursera
// if you are using this as middleware write next()
}else {
res.send(new Error("Error while connecting to coursera"));
// if you are using this as middleware write next(err)
}
);
}
And in the angular controller ..
app.controller('controller', function($scope, $http) {
$scope.getCoursera = function() {
$http({
url: "baseURL/coursera",
method: "GET",
}).success(function(data) {
$scope.data = data;
}).error(function(err) {
console.log(err);
});
};
});
I create a jwt token and stored in database. when login successfully done i want to redirect to home page with token. how could i do that.
My Nodejs file.
app.post('/authenticate', function(req, res, next) {
User.findOne({name: req.body.name}, function(err, user) {
if (err) {throw err;}
if (!user) {
res.json({ success: false, message: 'Authentication failed. User not found.' });
} else if (user) {
// check if password matches
if (user.password !== req.body.password) {
res.json({ success: false, message: 'Authentication failed. Wrong password.' });
} else {
// if user is found and password is right
// create a token
var token = jwt.sign(user, app.get('superSecret'), {
expiresIn: 1440 // expires in 24 hours
});
// return the information including token as JSON
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
}
});
});
My angularjs file
var app = angular.module('loginApp', []);
// Controller function and passing $http service and $scope var.
app.controller('loginCtrl', function($scope, $http) {
// create a blank object to handle form data.
$scope.user = {};
// calling our submit function.
$scope.submitForm = function() {
// Posting data to file
$http.post('/tokken/login/', $scope.user).then(function (response) {
//$http.defaults.headers.common['Token'] = token
if (response.errors) {
// Showing errors.
$scope.errorName = response.errors.name;
$scope.erroPassword = response.errors.password;
} else {
$scope.message = response.data;
}
});
};
});
I print token value in same login page. I want to redirect to another page with the token
My '/messages' API is used to query mongodb for document with given 'hostname' and 'day'. When I test it with 'postman' I got correct response, array of objects. But when angular client used, it gives me empty array [], why?
Controller
apiSvc.post('/messages', {hostname: "XYZ", day: '1'})
.then(function (response) {
console.log(response.data);
});
SERVICE
.factory("apiSvc", function($http) {
return {
post: function(url,data) {
return $http.post(url,data);
},
}
})
ROUTER
router.post('/messages', function (req, res, next) {
console.log(req.body.hostname, req.body.day);
Message.find({day: req.body.day, hostname: req.body.hostname},
function(err, message) {
res.send(message);
});
});
I have a login system in my website and I want to show the name of the user in the frontend using AngularJS, but I don't know how to pass the user from NodeJS
app.get('/main', isLoggedIn, function(req, res){
res.render('main.ejs', {
user : req.user
});
});
From the looks of the snippet you provided.
Your incoming data is already the user you wish to display.
In ExpressJS:
req stands for the Request, coming in from the Client.
res stands for the Response, going back to the Client.
Good article on ExpressJS Here, it goes a bit more in-depth.
If your goal is to contact the DB when you receive a username and password from the client, then display back the user's full name. Then do something like this.
Client (AngularJS)
app.service('SomeService', ['$http', function ($http, ) {
this.loginUser = function(user, pass) {
var model = {
user: user,
pass: pass
};
var promise = $http.post('/Account/Login', JSON.stringify(model))
.then(function(response) {
return {
response.fullName
};
}, function() {
//Error
};
});
return promise;
};
}]);
On your Server
app.get('/Account/Login', function(req, res) {
//Do Logic magic here....
return res.json({ fullName: 'John Doe'});
});
Finally your Controller and HTML
After doing the round trip, your JS Promise will be returned to the original caller of the Angular Service and you can populate a $scope variable then display it however you wish. Take a look:
app.controller("MyController", function('SomeService'){
$scope.fullName = '';
SomeService.loginUser ('userCool','password123')
.then(function (response) {
$scope.fullName = response.fullName;
}, function () {
//Some Error, Server did not respond...
});
});
HTML
<div ng-controller="MyController">
<label ng-bind="fullName"></label>
</div>
First, set it up on server side:
app.get('/api/:paramID1/:paramID2', function(req, res) {
return res.json({ user: 'example' });
});
On the client side you need an ajax call to invoke the service like:
$http.get( "/api/1/abc").success(function(data) {
$scope.user = data;
});