I've having issues with both my routes and getting/saving the data with mongodb. It seems to have validation errors when saving or maybe not posting JSON. Any ideas?
Here's my mongoose schema:
// grab the things we need
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// create a schema
var sitesEntrySchema = new Schema({
ip: {
type: String,
required: true,
trim: true
},
domain: {
type: String,
required: true,
trim: true
},
wp: {
type: String,
required: true,
trim: true
},
host_name: {
type: String,
required: true
},
hosted: {
type: Number,
required: true
}
});
// make this available to our users in our Node applications
var Site = mongoose.model('Site', sitesEntrySchema);
module.exports = Site;
And my angular http request
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope, $http) {
$http.get('/api/mongo')
.then(function(response) {
console.log(response.data);
$scope.myData = response.data;
});
});
app.controller('FormCtrl', function($scope, $http) {
$scope.formData = {};
$scope.addSite = function() {
$http.post('/api/create', $scope.formData)
.success(function(data) {
console.log($scope.formData);
$scope.formData = {}; // clear the form so our user is ready to enter another
swal(
'Good job!',
'Site was added!',
'success'
);
})
.error(function(data) {
console.log('Error: ' + data);
});
};
});
My express routes:
var express = require('express');
var router = express.Router();
var Site = require('../models/site');
//Return From Mongo
router.get('/api/mongo', function(req, res) {
Site.find({}, function(err, sites) {
if (err)
res.send(err)
res.send(sites);
});
//res.json({"yo": "yo this shit works"});
});
//Add A Site
router.post('/api/create', function(req, res, next) {
//create object with form input
var siteData = {
ip: req.body.ip,
domain: req.body.domain,
wp: req.body.wp,
host_name: req.body.host_name,
hosted: req.body.hosted
};
// use schema's 'create' method to insert doc into mongo
Site.create(siteData, function(error) {
if (error) {
//return next(error);
res.send(error);
} else {
return res.json({ message: 'Site added!' });
}
});
});
Without specific outputs that show what is going wrong, here are a few things stick out to me. The first is not always responding with json. You should also try using next() to handle your errors since Express will make sure to send back a correct error response. With these changes, your get route looks like:
//Return From Mongo
router.get('/api/mongo', function(req, res, next) {
Site.find({}, function(err, sites) {
if (err) {
next(err)
} else {
return res.json(sites);
}
});
});
Secondly, It is best practice to return the newly created resource, so your create route should look like
//Add A Site
router.post('/api/create', function(req, res, next) {
//create object with form input
var siteData = {
ip: req.body.ip,
domain: req.body.domain,
wp: req.body.wp,
host_name: req.body.host_name,
hosted: req.body.hosted
};
// use schema's 'create' method to insert doc into mongo
Site.create(siteData, function(error, site) {
if (error) {
next(error);
} else {
return res.json(site);
}
});
});
In addition, depending on your version of Angular, you might be using the deprecated promise syntax for the post request. You should be using .then(), not .success() and .error(). This might also be causing an issue.
Lastly, you should try your best to follow REST guidelines for your routes and responses. It will make it much easier to extend your web app and will keep you more organized. Here is a good Express/Node resource for that https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4.
ADDED: Here is an example of how you can log your errors depending on production/development environments
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
console.log('err:', err.status, err.message);
res.status(err.status || 500);
res.json({message: err.messages});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
Related
This is my Server.js file (NodeJS):
var express = require('express');
var server= require('http');
var path= require("path");
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var app= express();
var staticDIR = path.resolve(__dirname, "./www");``
app.use(express.static(staticDIR));
app.use(bodyParser.json());
app.get("*", function (req, res) {
var indexViewPath = path.resolve(__dirname, "./www/index.html");
res.sendFile(indexViewPath);
});
var dbURI = 'mongodb://localhost:27017/mydatabase';
mongoose.connect(dbURI);
mongoose.connection.on('connected', function () {
console.log('Mongoose connected to ' + dbURI);
});
mongoose.connection.on('error',function (err) {
console.log('Mongoose connection error: ' + err);
});
mongoose.connection.on('disconnected', function () {
console.log('Mongoose disconnected');
});
process.on('SIGINT', function() {
mongoose.connection.close(function () {
console.log('Mongoose disconnected through app termination');
process.exit(0);
});
});
var userSchema = new mongoose.Schema({
name: String,
password:String,
email: {type: String, unique:true},
createdOn: { type: Date, default: Date.now }
//modifiedOn: Date,
//lastLogin: Date
});
mongoose.model( 'User', userSchema );
var User = mongoose.model('User');
var CompanySchema = new mongoose.Schema({
CompanyName: String,
password:String,
email: {type: String, unique:true},
createdOn: { type: Date, default: Date.now }
//modifiedOn: Date,
//lastLogin: Date
});
mongoose.model( 'company', userSchema );
var company = mongoose.model('company');
User.find({}, function(err, users) {
if(!err){
console.log(users);
}
});
company.find({}, function(err, users) {
if(!err){
console.log(users);
}
});
app.post('/account', function(req, res){
new company({
CompanyName:req.body.Company,
email:req.body.email,
password:req.body.password
}).save(function(err,doc){
if(err)res.json(err);
else res.send("succesfully inserted");
console.log(res);
});
});
This is my Middleware to get tha data:
app.get('/details', function (req, res) {
console.log('I received a GET request');
company.find({}, function(err, users) {
if(!err){
console.log(users);
}
else{
res.render('/details',{users:docs})
}
});
});
app.listen(9000);
console.log("Server Running on port 3000");
This is my Controller.js (AngularJS) file:
angular.module('myApp', ['ngMaterial','firebase','ui.router'])
.controller('detailsCtrl', function($scope,myfirebaseAddress,$location,$timeout) {
var ref = new Firebase(myfirebaseAddress);
})
This is my route where I want to show the mongoDb saved data
<ui-view>
<div class="sub-header">
<h3>Company Details</h3>
</div>
<ul>
<li ng-repeat="users in user">
{{user.email}}
</li>
</ul>
</ui-view>
Thanks in advance
instead if writing below code
if(!err){
console.log(users);
}
else{
res.render('/details',{users:docs})
}
do like this
if(!err){
res.send(users);
}
else{
res.send('could not retrived data');
}
in controller side you can get your all data inside success call back function.here also check
app.listen(9000);
console.log("Server Running on port 3000");
this should like below.
app.listen(9000);
console.log("Server Running on port 9000");
Controller to get the requested data
.controller('detailsCtrl', function($scope,$http) {
$scope.users = [];
$http.get('/details').then(function(d)
{
console.log(d);
$scope.users= d.data;
},function(err)
{
console.log(err); }
)
})
server route
app.get('/details', function (req, res) {
console.log('I received a GET request');
company.find({}, function(err, users) {
if(!err){
res.json(users);
}
});
});
If you want to retrieve your data, you must stop this:
res.render('/details',{users:docs})
If you want to serve data with an angular app, you have to stop to render a view and start to give back a json in your response.
res.jsonp(users)
Then you've to adjust your controller.
Write a service like:
angular.module('yourApp')
.service('userService', function($http){
return {
getUsers: function(url) {
return $http.get(url)
}
}
})
this should return an http promise.
In your controller you handle this promise this way:
$scope.users = function(){
userService.getUsers('/users')
.then(function(users){
//You have your users object
})
}
remember to handle the unsuccesfull case of your promise
Try to use the angular http module to get the node/express response that get the data from mongodb in client side; like this: https://github.com/J-Alex/api_rest_mvc
In the view html page there is a form with a table and when i submit the form two objects are created cvm and schedules for form and table. i somehow want schedules(which is an array) to be related to cvm form. so i tried this way...
Here is the defined model
$scope.addSchedule=function(schedule)
{
console.log(schedule.startDate);
console.log(schedule.location);
$scope.schedules.push({
startDate: schedule.startDate,
location: schedule.location
});
schedule.startDate='';
schedule.location='';
};
var inData={'cvm': $scope.cvm,'schedules': $scope.schedules};
$scope.addCvm=function()
{
console.log($scope.cvm);
console.log($scope.schedules);
$http.post('/cvmApi',inData).success(function(response) {
console.log(response);
refresh();
});
};
sever side Connection
i guess somthing i missed in this part
/* POST */
router.post('/', function(req, res, next)
{
console.log("Cvm api post '/'");
console.log("retrieving:: " + req.body);
cvmModel.create(req.body, function (err, post) {
console.log("saving:: " + post);
if (err) return next(err);
res.json(post);
});
});
Here is my schema for mongodb
'use strict';
var mongoose = require('mongoose');
var cvmSchema = new mongoose.Schema({
visitOrganization: { type: String },
visitAgenda: { type: String },
accountManager: { type: String },
visitCoordinator: { type: String },
schedules:[{
startDate: String,
location: String
}]
});
module.exports = mongoose.model('visit', cvmSchema);
plz help !! thanks in advance
I think you should try with below change :
//Change addCvm function
$scope.addCvm = function(){
var inData = $scope.cvm;
inData.schedules = $scope.schedules;
console.log(inData);
$http.post('/cvmApi',inData).success(function(response) {
console.log(response);
refresh();
});
};
// Server Side API Code
router.post('/cvmApi', function(req, res, next) {
console.log("Cvm api post '/'");
console.log("retrieving:: " + req.body);
cvmModel.create(req.body, function (err, post) {
console.log("saving:: " + post);
if (err) return next(err);
res.json(post);
});
});
The thing is i dint realize my variable startDate was not in type string in my html page as i was using some date plugins....
soo ya thats it worked brilliantly ...
addCvm function in controller thanks to rana ;-)
$scope.schedules=[];
$scope.addCvm = function(){
var inData = $scope.cvm;
inData.schedules = $scope.schedules;
console.log(inData);
$http.post('/cvmApi',inData).success(function(response) {
console.log(response);
refresh();
});
};
server side Api
router.post('/', function(req, res, next) {
console.log("Cvm api post '/'");
console.log("retrieving:: " + req.body);
cvmModel.create(req.body, function (err, post) {
console.log("saving:: " + post);
if (err) return next(err);
res.json(post);
});
});
may be not required but i changed my schema though....
var cvmSchema = new mongoose.Schema({
visitOrganization: { type: String },
visitAgenda: { type: String },
accountManager: { type: String },
visitCoordinator: { type: String },
schedules: [{
dateStart: { type:String },
locationHere: { type: String }
}]
});
I'm new to the stack and am building a test page to sort out my understanding before building my actual project. Right now, I'm just trying to take user input, save it to a database, and print it. The data should be saved in a basic Mongoose model, test. While all of the routes are open, instead of printing what the user entered it prints something in the following format:
{"_id":"55c3925b48b9dba0d896be40","__v":0}
I suspect it has something to do with the second line of this snippet from index.js:
router.post('/survey', function(req, res, next) {
var test = new Test(req.body);
test.save(function(err,test) {
if(err) {
return next(err);
}
res.json(test);
});
});
module.exports = router;
Relevent code:
All of index.js:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
//set up routes
var mongoose = require('mongoose');
var Test = mongoose.model('Test');
router.get('/survey', function(req, res, next) {
Test.find(function(err, tests) {
if(err) {
return next(err);
}
res.json(tests);
});
});
router.post('/survey', function(req, res, next) {
var test = new Test(req.body);
test.save(function(err,test) {
if(err) {
return next(err);
}
res.json(test);
});
});
module.exports = router;
Tests.js (model):
var mongoose = require('mongoose');
var TestSchema = new mongoose.Schema({
'name': String,
});
module.exports = mongoose.model('Test', TestSchema);
Relevant bits of angular code:
routerApp.factory('tests', ['$http', function($http){
var o = {
tests: []
};
o.getAll = function() {
return $http.get('/survey').success(function(data){
console.log('get all sees data as:' + data);
angular.copy(data, o.tests);
});
};
o.create = function(test) {
console.log('create sees test as' + test);
return $http.post('/survey', test).success(function(data){
o.tests.push(data);
console.log('Data:' + data);
});
};
return o;
}]);
routerApp.controller('FormCtrl', ['$scope', 'tests',
function($scope, tests){
$scope.test = tests.tests;
$scope.addTest = function(){
if(!$scope.text || $scope.text === '') { return; }
tests.create({
name: $scope.text
});
$scope.text = '';
};
}
]);
I suspect this is a matter of not understanding what kind of object req is, but I'm not entirely positive. How would I go about making this code save data in the format described in the mongoose model?
If you call .toObject() on the document object (res.json(test.toObject())), you should get a plain object back containing the data in that document.
Try to console.log(req.body). If it's empty, then try adding app.use(bodyParser.json()) somewhere before your routes are defined (and be sure to install it with npm and require it first).
When you POST some sort of JSON, it isn't available in req.body by default. You need bodyParser to parse the incoming data and make it available in req.body. See https://medium.com/#adamzerner/how-bodyparser-works-247897a93b90 for more info.
I"m having trouble authenticating to an Active Directory Server with the tools/applications mentioned in the title.
I'm using a test AD environment found here
Here are the relevant code snippets, if anyone has any suggestions I would really appreciate it.
Currently, the error i'm getting is "invalid username/password". I'm not sure if this is the bindDn account/pw or the one the user enters in the form. According to the passport-ldapauth project it's:
invalidCredentials flash message for InvalidCredentialsError
NoSuchObjectError, and
/no such user/i LDAP errors (default: 'Invalid username/password')
Thanks in advance.
CLIENT - auth.service.js
...
login: function(user, callback) {
var cb = callback || angular.noop;
var deferred = $q.defer();
$http.post('/auth/ldap', {
email: user.email,
password: user.password
}).
success(function(data) {
$cookieStore.put('token', data.token);
currentUser = User.get();
deferred.resolve(data);
return cb();
}).
error(function(err) {
this.logout();
deferred.reject(err);
return cb(err);
}.bind(this));
return deferred.promise;
},
...
SERVER index.js
'use strict';
var express = require('express');
var passport = require('passport');
var auth = require('../auth.service');
var router = express.Router();
router.post('/', function(req, res, next) {
passport.authenticate('ldapauth', function (err, user, info) {
var error = err || info;
if (error) return res.json(401, error);
if (!user) return res.json(404, {message: 'Something went wrong, please try again.'});
var token = auth.signToken(user._id, user.role);
res.json({token: token});
})(req, res, next)
});
module.exports = router;
SERVER passport.js
var passport = require('passport');
var LdapStrategy = require('passport-ldapauth').Strategy;
exports.setup = function (User, config) {
passport.use(new LdapStrategy({
usernameField: 'email',
passwordField: 'password',
server: {
url: 'ldap://ldap.forumsys.com:389',
bindDn: "cn=read-only-admin,dc=example,dc=com",
bindCredentials: "password",
searchBase: 'ou=mathematicians,dc=example,dc=com',
searchFilter: 'uid={{username}}'
}
},
function (user, done) {
return done(null, user);
}
));
};
The problem is with the ou=mathematicians in the search base. There is the following mention in the comments on that web page:
The issue you are seeing is due to the fact that “uid=riemann” is a member of “ou=mathemeticians”, but does not reside under that ou. His membership in that ou is established by a uniqueMember attribute on “ou=mathemeticians”.
This should work (tried it even with ldapauth-fork which passport-ldapauth uses):
var opts = {
server: {
"url": "ldap://ldap.forumsys.com:389",
"adminDn": "cn=read-only-admin,dc=example,dc=com",
"adminPassword": "password",
"searchBase": "dc=example,dc=com",
"searchFilter": "(uid={{username}})",
}
};
For whose still lose your way, here is my code snippet in Typescript.
Server Side
import * as express from 'express'
import * as bodyParser from 'body-parser'
import * as cors from 'cors'
import * as passport from 'passport'
import * as ldapstrategy from 'passport-ldapauth'
// connect to LDAP server
const OPTS: ldapstrategy.Options = {
server: {
url: "ldap://ldap.forumsys.com",
bindDN: "cn=read-only-admin,dc=example,dc=com",
bindCredentials: 'password',
searchBase: "dc=example,dc=com",
searchFilter: "(uid={{username}})"
}
}
passport.use(new ldapstrategy(OPTS))
// instantiate the server
const app = express()
// parse the request data automatically
app.use(bodyParser.json())
// allow cross origin resource sharing
app.use(cors())
// inject LDAP connection to express server
app.use(passport.initialize())
// listen to port defined
const port = process.env.PORT || 8085
app.listen(port, (): void => {
console.log(`Listening on port ${port}`)
})
app.post('/login', (req: express.Request, res: express.Response, next: express.NextFunction): void | Response => {
passport.authenticate('ldapauth', (err, user, info): void => {
var error = err || info
if (error)
res.send({
status: 500,
data: error
})
if (!user)
res.send({
status: 404,
data: "User Not Found"
})
else
res.send({
status: 200,
data: user
})
})(req, res, next)
})
Client Side
Your code looks correct, but the error you're getting leads me to believe you really don't have the correct username/password supplied! Are you sure you're testing with the right credentials?
As a sidenote -- if you're looking for a simpler way to do this for a big project, and don't mind spending some money, Stormpath's API service does this sort of thing for you: it basically syncs your AD / LDAP users into it's API service so you can work with them via a REST API (it's much simpler).
There are two libraries you can use to work with it:
express-stormpath
passport-stormpath
Both are pretty simple / nice to use.
this code me
phpLDAPadmin express.js and passport-ldapauth
var express = require('express'),
passport = require('passport'),
LdapStrategy = require('passport-ldapauth');
const OPTS = {
server: {
url: 'ldap://localhost:389',
bindDN: 'cn=admin,dc=ramhlocal,dc=com',
bindCredentials: 'password',
searchBase: 'dc=ramhlocal,dc=com',
searchFilter: '(uid={{username}})'
}
};
var app = express();
passport.use(new LdapStrategy(OPTS));
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.use(passport.initialize());
app.post('/login', function (req, res, next){
passport.authenticate('ldapauth', {session: false}, function(err, user, info) {
var error = err || info
console.log(user);
if (error)
res.send({
status: 500,
data: error
})
if (! user) {
res.send({
status: 404,
data: "User Not Found"
})
}
res.send({
status: 200,
data: user
})
})(req, res,next)
})
app.listen(8080);
enter image description here
I am using mongoose to create a user object on register. This works fine and any errors are returned as expected.
However, I want to log the user on right after they register (so registering logs you on if there are no errors).
I have the following for the register.
register_controller:
$scope.submitRegister = function() {
AuthenticationService.register(this.details).success(function() {
$log.debug('/POST to /api/register worked');
});
}
services.js:
.service('AuthenticationService', function($http, $timeout, $q, $session, $flash) {
...
this.register = function(details) {
var register = $http.post('/api/register', details);
register.success(function() {
console.log("User added fine");
}).error(function() {
console.log("error!!!");
});
return register;
};
...
users.js:
app.post('/api/register', authentication.register);
passport's authenticate.js:
module.exports = {
...
register: function(req, res){
var User = require('./controllers/api/login_api');
User.create({name: req.body.name, email: req.body.email, password: req.body.password}, function(err){
if (err) {
console.log(err);
return;
}
console.log("User added");
return res.send(200);
});
},
...
The error is reported back fine, no troubles, but I would have thought it would report something else back (like the created object?) which I could use down the line so my register_controller can have in the success function(object) {... login(object);...}.
Is this a limitation in the .create method or am I missing something obvious?
Thank you.
Two things to change in your server code:
passport's authenticate.js:
module.exports = {
...
register: function(req, res){
var User = require('./controllers/api/login_api');
User.create({name: req.body.name, email: req.body.email, password: req.body.password}, function(err, user){
if (err) {
console.log(err);
return;
}
console.log("User added");
return res.send(200, user);
});
},
...
I've added user to your callback Mongoose model.create api - return the created object to the CB
And to change the catch in your client:
.service('AuthenticationService', function($http, $timeout, $q, $session, $flash) {
...
this.register = function(details) {
var register = $http.post('/api/register', details);
register.success(function(user) {
console.log(user);
}).error(function() {
console.log("error!!!");
});
return register;
};
...
Now you can do with the created user object whatever you need