Mongoose query via Angular variable - angularjs

I´m trying to query my mongoose model with an angular variable - an email adress.
I´ve got a variable from passport with contains the email <%= user.local.email %>.
The $http.getfor my Model looks like this:
app.get('/profile/project/:mail', function (req, res, next){
Project.findOne(req.params.mail, function (err, doc){
if(err) return next(err);
res.json(doc);
});
});
I can´t figure out how to pass the mail adress with the angular controller, to the GET request.
My try:
$http.get('/profile/project/' + <%= user.local.email %>).then(function (res){
$scope.project = res.data;
});
});
Setting the findOne parameter to a fixed mail adress worked, but I´ve got no idea how to pass the mail adress with the angular controller.
Hope you can help me.
Best regards, David
Update using passport
Getting near the solution, but now I only get the first data entry of my DB.
Sum it up, my route:
app.get('/profile/project/', function (req, res, next){
Project.findOne(req.user.local.email, function (err, doc){
if (err) return next(err);
if (!doc) return next(new Error('cant find'));
console.log(doc);
res.json(doc);
});
});
My angular controller:
<script>
var app = angular.module('myApp', []);
app.controller('projectCtrl', function($scope, $http) {
$http.get('/profile/project/').then(function (res){
$scope.project = res.data;
});
});
</script>
Passport works,I can log in and show the email address on the profile page. But with this route I´m just getting the first [0] entry from my database.

Are you sure you want angular to pass this variable?
If it's in passport, then it's likely the user's own email? If so then you should just look it up entirely on the backend.
If the email is really being passed from angular, then it doesn't make sense to have it in passport at all, and you would just pass it as a js var.
Edit
findOne should only return one result. Maybe you need to use find if you are trying to get multiple records.

Got the solution. Big thanks to #Austin_Greco!
Route:
app.get('/profile/project/', isLoggedIn, function (req, res, next){
Project.findOne({'author' : req.user.local.email}, function (err, doc){
if (err) return next(err);
if (!doc) return next(new Error('cant find'));
console.log(doc);
res.json(doc);
});
});
Angular Controller:
$http.get('/profile/project/').then(function (res){
$scope.project = res.data;
});

Related

show current user information from node to angular

I want to show current user information from nodejs to angular(view).
The problem is that i don't know how to pass and how to get User Id in node and angular .
Code :
Node
router.get('/:id/api/data.json', function(req, res, next) {
console.log(req.params.id);
var userId = req.params.id;
User.findById({_id:userId}, function (err, doc) {
if (err) throw err
if (doc){
res.json({
doc: doc,
userID:req.params.id
});
}
});
});
Angular :
app.controller('profileCtrl', function($scope, $http) {
$http.get("don't know how to get id from node").then(function (response) {
console.log(response.data);
});
});
Your Node.js router is listening to the url /:id/api/data.json. The :id part of that means Node.js is expecting a paramater there, which will get picked up by req.params.id in your Node.js file.
This means that you actually have to be passing in an id value as a part of the url. So your url would look something like /userid12345/api/data.json.
In your Angular file, that's the url you're going to be making the get request to. Which means you need to know the user's ID in your Angular file so you can get that specific url, e.g.:
var userId = 'userid12345';
$http.get('/' + userId + '/api/data.json').then(function(response) {
console.log(response);
});
Once you pass userId in as a part of the url, then Node can grab it using req.params.id and you can make your db call.

node express routing params not catching

I have this
router.put('/user:resourceId', function(req, res) {
User.findOneAndUpdate({resourceId: req.params.resourceId}, req.body, function(err, user) {
if (err)
res.send(err);
res.send(user);
});
});
and in my angular code I have
updateResource: function(resource){
var self = this;
return $http.put('api/resources/resource', resource, {params:{resourceId:resource.resourceId}}).then(function(response){
return response.data;
}, function(err){
$log.error('Error updating', err);
});
}
Why isn't this path catching? It works when I remove the params.
Your route looks a little off, try the following:
router.put('/user/:resourceId', function(req, res) {
...
});
For a URL that looks like: /user/123, where req.param.resourceId is 123.
It looks like your angular code is pointing to /api/resources/resource though, so I can understand why it's perhaps not matching your Express route for /user/:resourceId - (Unless your Express router is set to handle request for something like the following: /api/resources/resource/user/:resourceid?

Updating database with node.js and angular

I have an app which posts, gets and deletes data and I would like to add 'update' functionality as well but I can't figure it out..
I have a node.js server which has such api:
app.get('/api/feedbacks', function(req, res) {
// use mongoose to get all feedbacks in the database
getfeedbacks(res);
});
// create feedback and send back all feedback after creation
app.post('/api/feedbacks', function(req, res) {
// create a feedback, information comes from AJAX request from Angular
FeedBack.create(req.body, function(err, feedback) {
if (err)
res.send(err);
// get and return all the feedbacks after you create another
getfeedbacks(res);
});
});
// delete a feedback
app.delete('/api/feedbacks/:feedback_id', function(req, res) {
FeedBack.remove({
_id : req.params.feedback_id
}, function(err, feedback) {
if (err)
res.send(err);
getfeedbacks(res);
});
});
and such angular service which speaks to node api:
service.factory('FeedBacks', ['$http',function($http) {
return {
create : function(feedBackData) {
return $http.post('/api/feedbacks', feedBackData);
},
get : function() {
return $http.get('/api/feedbacks');
},
delete : function(id) {
return $http.delete('/api/feedbacks/' + id);
}
}
}]);
That way I can post, get and delete data.
My goal is to add also update function.
What I have tried on node:
// update a feedback
app.put('/api/feedbacks/:feedback_id', function(req, res) {
// edit a feedback, information comes from AJAX request from Angular
FeedBack.put(req.body, function(err, feedback) {
if (err)
res.send(err);
// get and return all the feedbacks after you edit one
getfeedbacks(res);
});
});
on Angular service:
update: function(editFeedId, editedFeed){
return $http.put('/api/feedbacks/' + editFeedId, editedFeed);
}
controller looks like:
$scope.editFeed = function(id) {
$scope.editFeedId = id;
$scope.editedFeed = 'replace this txt'
FeedBacks.update($scope.editFeedId, $scope.editedFeed)
// if successful creation, call our get function to get all the new
feedBacks
.success(function(data) {
console.log('updated');
$scope.feedbacks = data;
});
};
I get 500 error as I execute editFeed(). I couldn't figure out to configure that! Where do I do wrong? Any Tips?
Thanks a lot in advance!
I'm assuming you're using Mongo here, in which case your update statement is incorrect.
It should be something like:
app.put('/api/feedbacks/:feedback_id', function(req, res) {
FeedBack.update({_id: req.params.feedback_id}, req.body, function(err, feedback) {
if (err)
res.send(err);
// get and return all the feedbacks after you edit one
getfeedbacks(res);
});
});

How can I return a database query and redirect at once?

I don't literally need to use "res.redirect()", I just mean I want to take the user to a different page using any workable method.
After the user enters their info, they click a button which calls createUser. createUser successfully adds a new entry to the database. I want the user to also be automatically redirected back to the index page ("/"). I have not found any way to do this. What I have below does hit "app.get('/'), but no redirect happens. Is it possible to put the redirect in app.post('/api/register-new-user')? Can I use window.location somehow within createUser? I have tried both of those ways to no avail.
// CLIENT =====
$scope.createUser = function() {
$http.post('/api/register-new-user', $scope.formData)
.success(function(data) {
$scope.formData = {}; // clear the form so our user is ready to enter another
$scope.users = data;
console.log(data);
// window.location = "./";
})
.error(function(data) {
console.log('Error: ' + data);
});
$http.get('/')
.success(function(data) {
})
.error(function(data) {
console.log('Error: ' + data);
});
};
//SERVER========
app.post('/api/register-new-user', function(req, res) {
bcrypt.genSalt(10, function(err, salt) {
if(err)
res.send(err);
bcrypt.hash(req.body.password, salt, function(err, hash){
if(err)
res.send(err);
User.create({
username : req.body.username,
password : hash
}, function(err, user) {
if(err)
res.send(err)
User.find(function(err, users) {
if(err)
res.send(err);
res.json(users);
});
});
});
});
});
app.get('/register', function(req, res) {
console.log('register');
res.sendfile('./public/views/register.html');
});
OK, so you are doing your browser/server interaction to create a user via AJAX and HTTP redirects over AJAX have no bearing on the URL/page loaded in the browser. So you can forget about server side HTTP redirects. Just send a 201 status to be nicely RESTful and call it good on the server.
On the client, if the POST succeeds you can just trigger a new route with $location.path('/');. Just make sure you declare $location so it gets injected by DI into your controller.
Also note that the active user probably needs to be set on the $rootScope if you want it to be broadly available to the rest of your controllers.
You could try
window.location.href()
Instead of window.location().
This should work with an absolute path.
Although as you are using Angular so it is possible to use the route provider to update the view with out redirecting the user.
Here is some documentation for the route provider.
https://docs.angularjs.org/tutorial/step_07

Passport.js Google authentication returns blank error

Trying to use passport.js in my Angular app to use google authentication.
The way I have my express endpoints set up is:
app.set('client-google-signin-path', '/google');
app.route('/auth/google')
.get(function(req, res, next) {
var mobileApp = req.headers.origin;
passport.authenticate('google', { scope: ['profile', 'email'], callbackURL: mobileApp + req.app.get('client-google-signin-path')})(req, res, next);
});
app.route('/auth/google/callback')
.get(function(req, res, next) {
//NEVER MAKES IT HERE
var mobileApp = req.headers.origin;
passport.authenticate('google', {scope: ['profile', 'email'], callbackURL: mobileApp + req.app.get('client-google-signin-path')},
function(err, user, info) {
var profile;
if(err) return next(err);
if(!info || !info.profile) return res.status(400).send("Profile not available.");
// Grab the profile info returned from google.
profile = info.profile._json;
//model logic
User.findOne({ 'email': profile.email }, function(err, user) {
if(err) return next(err);
if(!user) return res.status(400).send("There does not appear to be an account that matches, you may need to create an account and try again.");
req.logIn(user, function(err) {
if(err) return next(err);
return res.status(200).send(user);
});
});
res.status(200);
})(req, res, next);
});
My controller looks like:
$scope.signInGoogle = function() {
return $http.get(backendConst.location + 'auth/google')
.success(function(url) {
// Redirect to google.
$window.location.href = url;
});
};
$scope.signInGoogleCallback = function() {
return $http.get(backendConst.location + 'auth/google/callback', {
params: $location.search()
})
.success(function(user) {
$scope.gRes = 'Success!';
$location.search('code', null);
$location.hash(null);
AuthModel.setUser(user);
$location.path('/');
})
.error(function(err) {
$scope.gRes = 'Authentication failed, redirecting.';
$location.path('/authenticate');
});
And for good measure, my dinky little /google redirect page is:
<div class="container clearfix" ng-init="signInGoogleCallback()">
<h1>Google YO!</h1>
<h4>{{gRes}}</h4>
</div>
So what's happening is that it brings in the "log in with google" page, lets me select my account, then when it calls the callback it quickly flashes the /google view but then kicks me back out into /authenticate, the view I started in. Doing some debugging shows that
return $http.get(backendConst.location + 'auth/google/callback', {
params: $location.search()
})
is throwing a blank "err" even though in my endpoint logs it's saying that /auth/google/callback returned a 200. I'm not sure what's happening. I know this looks needlessly complicated but I do it this way with facebook and passport.js and everything works fine, except my endpoint logs are showing that with facebook the parameter "?code=" is being added to the /auth/facebook/callback url, like I'm trying to do with {params: $location.search()} in my google callback function in my controller. Debugging into the endpoint shows that it never makes it to where I left the //NEVER MAKES IT HERE comment, but when removing the {params: $location.search()} option it makes it passport.authenticate but not beyond. I'm completely stumped. Again I should stress that I handle facebook authentication the exact same way and it works perfectly.

Resources