Yeoman Angular-fullstack generator post error - angularjs

I'm using the Angular-fullstack generator to learn how Angular communicates with Mongoose. After running grunt serve without modifying any files, the Sign up form doesn't work giving a POST 400 (Bad Request).
Where should I do the modifications to get POST create a new user in the database?
An example I uploaded to Openshift.

I had the same problem, this is how I solved:
On file: /lib/controllers/users.js on the create function, change req.body and use req.query instead.
/**
* Create user
*/
exports.create = function (req, res, next) {
var newUser = new User(req.query);
newUser.provider = 'local';
newUser.save(function(err) {
if (err) return res.json(400, err);
req.logIn(newUser, function(err) {
if (err) return next(err);
return res.json(req.user.userInfo);
});
});
};
Regards

Related

Ionic + Passport isAuthenticated() returns false

I have my app in angularJs 1.6 built with MEAN stack working well, i'm using passport for authentication.
When I decide to test it with ionic, the app itself works well (files are basically identical) but the authentication with passport is broken
I can register and login a user, but when I want to check if the user is logged by using req.isAuthenticated() on my server, it always answers false.
I think it's because when I make a request from my normal angular app, the request contains a user object with password and email, but when I do from my ionic app, the user is missing
I've spend the day working on it, any help would be great !
EDIT 1:
Sorry for not including code, it's my first experience here
My login route + my function for login
app.post('/api/login', login);
function login(req, res, next) {
//console.log(req);
passport.authenticate('local-login', function(err, user, info) {
if (err) {
return next(err); // will generate a 500 error
}
// Generate a JSON response reflecting signup
if (! user) {
return res.send({success : 'false', message : req.flash('loginMessage') });
}
req.login(user, function(err) {
if (err) { return next(err); }
//console.log(req);
return res.send({success : 'true', message : req.flash('loginMessage') });
});
})(req, res, next);
}
The problem is, req.login is executed and I get a success: true, but with the ionic/cordova app, nothing seems to be memorized
After that, when I try to check if the user is logged with this
app.get('/api/login/loggedin', function(req, res) {
res.send(req.isAuthenticated() ? req.user : '0');
});
I always get '0', I think it is because cordova/ionic app cannot use cookies (the difference between requests is also the lack of cookie from the ionic one), but I can't understand how to manage a solution that works both with my web angular app and it's ionic version (still with passport)
Solution I just found:
In fact, it was a CORS problem because I don't know exactly why but Ionic/cordova didn't put {user:...} informations in the post request
Simply add
var cors = require('cors');
app.use(cors({origin: 'http://localhost:8100', credentials: true}));
to your server, it allows req to contains informations needed
and add
{withCredentials: true}
to all of your requests that are going to be checked with isAuthenticated(). For example:
$http.get('http://localhost:8081/api/todos', {withCredentials: true});
So the request sent contains the {user:...} part
I don't exactly know why you need to authorize it both in client and server side but it works fine

NodeJS- Export from SQL Server according to Stream

I work on a web application in NodeJS, and now I want add a module for exporting massive records from my SQL Server's database (10.000.000 records) according to stream/socket to a .CSV file.
If 100 users downloading data (.csv) from server, increased lot of memory usage in server / client.
I want if possible, save data(.csv) into hard drive(client), no into server/client Memory(RAM).
Server.js
var http = require('http');
var express = require('express');
var app = express();
var server = http.Server(app);
var io = require('socket.io')(server);
io.on('connection', function (socket) {
console.log('Connection is ready!')
socket.on('get_records', function (data) {
var connection = new sql.Connection(config, function (err) {
if (err) {
console.log(err.message);
}
var request = new sql.Request(connection);
request.stream = true;
request.query("Select * from my_table");
// ... error checks
request.on('recordset', function (recordset) {
// Emitted once for each recordset in a query
});
request.on('row', function (record) {
// Emitted for each row in a recordset
socket.emit('recieve_records', record); //send record by record to client
});
request.on('error', function (err) {
console.log(err.message);
});
request.on('done', function (returnValue) {
// Always emitted as the last one
});
});
});
Edit: See below post
StreamSaver.js - Error in downloading (Network failed)
If you transfer a file using socket.io there is no easy/robust way to initiate the download dialog. I found 3 solutions to save the file:
This answer. But you'll have to keep the whole file in RAM before save. + it has max blob size restriction.
FileSaver module. Same idea, wrapped into a module (5k stars at GitHub). Still restricted to blob size, and keeps everything in memory.
StreamSaver module. Doesn't have blob size restriction. But doesn't work at all in Firefox, IE, Edge.
That is why I suggest you to use simple HTTP for file transfers.
Then you could simply use <a href="path/to/your/endpoint"> tag to download it or use some tricks from here.
So in case you have Node.js Readable stream that emits objects you can use 'csv' module and convert it to 'csv' on the fly. Then simply pipe it to Express response object.
var csv = require('csv');
router.get('/csv', function (req, res, next) {
//Handle the connection here, you might decide to use connection pool is supported
new sql.Connection(config, function (err) {
if (err) {
console.log(err.message);
}
//You can pipe mssql request as per docs
var request = new sql.Request(connection);
request.stream = true;
request.query("Select * from my_table");
var stringifier = csv.stringify({header: true});
//Then simply call attachment and pipe it to the response
res.attachment('sample.csv');
request.pipe(stringifier).pipe(res);
});
});
Also checkout the csv-stringify docs as there are useful options such as headers: true (to add headers row) and others.

Why do I get a mongoose ValidationError?

I am at a beginner level with the MEAN stack, trying to work on the following tutorial: adrianmejia.com/blog/2014/10/01/creating-a-restful-api-tutorial-with-nodejs-and-mongodb/. I am using Cloud 9 online IDE.
Part of the tutorial involves testing database POST using curl and Postman. I successfully post a GET request, which at this point in the tutorial gives med an empty array.
I use
curl -XGET myc9urlhere:8080/todos - with success (getting [])
And try curl -XPOST myc9urlhere:8080/todos -d 'name=Somename&completed=false&note=somenote' - failing
The stacktrace is as follows:
ValidationError: Todo validation failed
at MongooseError.ValidationError (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/error/validation.js:23:11)
at model.Document.invalidate (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:1486:32)
at model.Document.set (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:753:10)
at model._handleIndex (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:596:14)
at model.Document.set (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:556:24)
at model.Document (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:68:10)
at model.Model (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:47:12)
at new model (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:3250:13)
at /home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:1864:51
at /home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/internal/parallel.js:27:9
at eachOfArrayLike (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/eachOf.js:57:9)
at exports.default (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/eachOf.js:9:5)
at _parallel (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/internal/parallel.js:26:5)
at parallelLimit (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/parallel.js:85:26)
at /home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:1882:5
at Function.create (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:1852:17)
A small note is that I have also tried this using the Chrome extension Postman. The tutorial says I must use x-www-form-urlencoded which gives the same error returned. See screenshot. And if I turn to the form-data setting instead, I actually succeed in inserting some data into the database, but just bogus stuff. See the second screenshot.
Postman fail
Postman form-data
I have really tried to research myself - maybe this tutorial is not the greatest place to start either :). Below I will include some details on the code.
Thanks a lot for any help solving this.
Identical to the tutorial, I have created a Model for a todo-list item, as shown (Todo.js):
var mongoose = require('mongoose');
var TodoSchema = new mongoose.Schema({
name: String,
completed: Boolean,
note: String
});
module.exports = mongoose.model('Todo', TodoSchema);
Now in my express routing file todos.js I have the following code:
var express = require('express');
var router = express();
//express.Router() was the original here, that failed on router.get
//as router was then undefined for some reason.
var Todo = require('../models/Todo.js');
/* GET /todos listing. */
router.get('/', function(req, res, next) {
Todo.find(function (err, todos) {
if (err) return next(err);
res.json(todos);
});
});
/* POST /todos */
router.post('/', function(req, res, next) {
Todo.create(req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
module.exports = router;
Because I do not know exactly what is wrong here I will also post an extract of my app.js showing my database connection
var routes = require('./routes/index');
var users = require('./routes/users');
var todos = require('./routes/todos');
var app = express();
// load mongoose package
var mongoose = require('mongoose');
// Use native Node promises
mongoose.Promise = global.Promise;
// connect to MongoDB
mongoose.connect('mongodb://'+process.env.IP+'/todo-api')
.then(() => console.log('connection succesful'))
.catch((err) => console.error(err));
app.use('/', routes);
app.use('/users', users);
app.use('/todos', todos);
And the package-json that was generated (I am using Cloud 9 IDE)
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"ejs": "*",
"express": "3.2.6",
"mongoose": "^4.7.6"
}
}
I think the main problem you're encountering here is that all post parameters are strings. This ends up being fine for the name and note fields of you TodoSchema, but will break when it comes to the completed field, since it is boolean. To address this, try converting the string to a boolean before creating the ToDo entry.
/* POST /todos */
router.post('/', function(req, res, next) {
req.body.completed = (req.body.completed === 'true');
Todo.create(req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
Also, the reason that the bogus post worked is because you aren't validating your post data. Consider making sure that the post data coming in though your route has all of the required fields, and doesn't contain anything dangerous.
Go to the data folder in your directory. Inside it there is a file mongod.lock. Delete it (you wont require root privileges) just use rm mongod.lock. Come back to main directory and enter ./mongod. hope this will solve the problem

POST request using angular $resource

In my index.js file I have the following POST...
router.route('/bears')
// create a bear (accessed at POST http://localhost:8080/api/bears)
.post(function(req, res) {
var bear = new Bear(); // create a new instance of the Bear model
bear.name = req.body.name; // set the bears name (comes from the request)
// save the bear and check for errors
bear.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Bear created!' });
});
})
.get(function(req, res) {
Bear.find(function(err, bears) {
if (err)
res.send(err);
res.json(bears);
});
});
I test the url http://localhost:8080/api/bears with a POST request on Postman and it was successful. Now I'd like to test my POST request using angular $resource.
I tried the following which I got from the documentation...
app.factory('Profile', function ($resource) {
var Bear = $resource('http://XXX.XXX.X.XX:3000/api/bears/:bearId', {bearId:'#id'});
var single_bear = Bear.post({bearId:123}, function(){
single_bear.name = "Yogi";
single_bear.$save();
});
});
I'm not sure what I should for bearId, I just put a random number. And I am trying to save the bear's name as Yogi. I'm assuming this POST request will occur when I run the app, but I do so and then check to see if my db was filled and there is no entry.
What am I doing wrong?
EDIT
in case you're wondering what a bear entry looks like...
{
"_id": "57ded2302a5ebc050ce3852d",
"__v": 0,
"name": ""
}
Your resource is configured to look for the id property in the data passed (via '#id') yet your data is passing bearId.
Additionally, the data from your server seems to have an _id property, not id nor bearId.
Also, the resource method you're looking for is save(), not post().
I'd go with this type of resource definition...
$resource('http://XXX.XXX.X.XX:3000/api/bears/:id', {id:'#_id'});
Then, you can use it to create a new Bear via
Bear.save({_id: 123, name: 'Yogi'})

How to implement customGet in restangular?

How to implement customGet from restangular?
I wrote some code in a server like this:
user.controller.js:
exports.getRunner = function(req, res) {
User.find({provider: "instagram"}, function (err, users) {
if (err) return res.send(500, err);
res.json(200, users);
});
};
index.js:
router.get('/getRunner', controller.getRunner);
If I try to get data from postman... it responds the right json data, it works properly.
But when I try using Restangular customGet in my client side, I get instead an undefined error.
This is my client side:
Restangular.all('users').customGET('getRunner').then(function(teams) {
$scope.teams = teams;
});

Resources