im currently trying nodejs for the first time and im trying to make a rest api that i can link to my website that uses postgresql to get the data.
categories.js is the file im currently working on, it holds all get and post methods related to the categories table in postgres
Here's the current code in my categories.js:
var express = require('express');
const bodyParser = require("body-parser");
var router = express.Router();
const {Client} = require('pg');
router.use(bodyParser.json());
const client = new Client({
host: 'localhost',
user: 'postgres',
port: 5432,
password: 'admin123',
database: 'postgres'
})
client.connect();
/* GET categories listing. */
router.get('/', function(req, res, next) {
client.query(`select * from categories`, (err, result)=>{
if(!err){
res.send(result.rows);
}
else console.log(err.message);
});
client.end;
});
/* GET category listing by id. */
router.get('/:id', function(req, res, next) {
client.query(`select * from categories where id=${req.params.id}`, (err, result)=>{
if(!err){
res.send(result.rows);
}
else console.log(err.message);
});
client.end;
});
/* POST category listing by postman. */
router.post('/', (req, res)=> {
const category = req.body;
console.log(category)
let insertQuery = `INSERT INTO categories
(name, createdat)
VALUES ('${category.name}','${category.createdat}');`
client.query(insertQuery, (err, result)=>{
if(!err){
res.send('Insertion was successful')
}
else{ console.log(err.message) }
})
client.end;
})
module.exports = router;
the problem is, everytime i try to make a post method through postman using this script:
{
"name": "cat2",
"createdat": "13/05/201"
}
it posts an empty item into the database:
{"id":12,"name":"undefined","available":true,"createdat":"undefined"}
the get methods work normally by the way, but the post method doesn't
here's the categories table in postgres incase that helps
CREATE TABLE IF NOT EXISTS public.categories
(
id integer NOT NULL DEFAULT nextval('categories_id_seq'::regclass),
name text COLLATE pg_catalog."default" NOT NULL,
available boolean NOT NULL DEFAULT true,
createdat text COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT categories_pkey PRIMARY KEY (id)
)
well well well, i found what the problem was lmao, and its actually embarassing.
well basically in the postman program, when i was inputing my data for it to be submitted to the database as json, i had the body selected in text form instead of json, which is why it couldnt recognize my data, cs it was in txt not json..
here's a pic incase someone does a stupid like i did
fix
mistake
Related
I'm using React Admin for the first time, and my users (coming from mongoDB) are displayed just fine. The problem occurs when I click the "edit" (or "delete") button on a specific user: it says "GET http://localhost:3002/api/users/2a1a3a61-f73b-4a01-b609-ae4bb815f59e 404 (Not Found)"
I use "http://localhost:3002/api/users" to make the GET req to mongoDB: "app.use('/api/users', require('./api/GetUsers'))" and "2a1a3a61-f73b-4a01-b609-ae4bb815f59e" is the id of the user I clicked.
I remember when I first started testing React Admin, that I was using jsonplaceholder.typicode to get data and the edit function was working as well, although, of course, would not persist on refresh.
What am I missing? Is the problem the fact that my api's (http://localhost:3002/api/users) purpose is only getting the data and not post/put also, maybe?
/api/GetUsers
const express = require('express');
const mongoose = require('mongoose');
const ContactUser = require('../DB/ContactUser');
const router = express.Router();
const getUsers = async (req, res) => {
ContactUser.find()
.exec((err, user) => {
if(err){
res.json(err);
} else {
res.setHeader('Access-Control-Expose-Headers', 'Content-Range');
res.setHeader('Content-Range', 'users 0-20/20');
res.json(user);
}
})
};
router.route('/').get(getUsers);
module.exports = router;
/DB/ContactUser
const mongoose = require('mongoose');
const contactUser = new mongoose.Schema({
name: String,
email: String,
message: String,
id: String
});
module.exports = mongoose.model('contactUser', contactUser);
You're missing a second route to retrieve not a list of users, but a single user. It will use the id in the URL to find one user. Something like:
router.get('/:id', function(req, res) {
ContactUser
.findOne({ _id: req.params.id })
.exec((err, user) => err ? res.json(err) : res.json(user));
});
I'm building an application (MVC) that will use 4 collections in a DB. When I add new clients to the application they will get their separate DB. So if I have 10 customers, there will be 10 DBs and 40 collections (1 db -> 4 collections)
This way each customer data is seperated from other customers, which is crucial here.
So far I've built the app and everything is working nicely, 'cept one thing.
If Company A logs in and start using the app everything works fine. But when Company A is logged in, and Company B logs in, both Company A AND B will be directed towards Company B:s DB.
I've looked trough my code and I guess this is my own fault because I use .connect (mongoose). When a company logs in the route will fire of a controller that will open a new connection (which overrides the old one) which will redirect all open connections towards that specific DB.
controller.dBlogin.js
mongoose.connect(dbConfig.url + id, options)
.then(() => {
console.log("Successfully connected to the database");
next();
}).catch(err => {
console.log('Could not connect to the database. Exiting now...');
process.exit();
});
The id is fetched from req.params.id (example: http://webapp.com/login/:id).
As far as I've figured .connect only allows one connection at a given time so I need something that will, simply, allow many connections. So I'm thinking that I could use .createConnection for this,
https://mongoosejs.com/docs/connections.html#multiple_connections
But i just cant get it to work.
I changed controller.dBlogin.js to
mongoose.createConnection(dbConfig.url + id, options)
.then(() => {
console.log("Successfully connected to the database");
next();
}).catch(err => {
console.log('Could not connect to the database. Exiting now...');
process.exit();
});
but that only leads to a timeout when the company logs in. How do I use the .createConnections? How do you go from .connect to .createConnection?
Heres the examples of routes, controller, and a model (user-schema).
routes.js
// connect to db, check auth
app.post('/login/:id', dbController.connectDB, dbController.login)
controller.dbLogin.js
exports.**connectDB** = (req, res, next) => {
const id = req.params.id;
// Get Mongoose to use the global promise library
mongoose.Promise = global.Promise;
// Options Conncetion mongodb
const options = {
useNewUrlParser: true,
};
// Connecting to the database
mongoose.connect(dbConfig.url + id, options)
.then(() => {
console.log("Successfully connected to the database");
next();
}).catch(err => {
console.log('Could not connect to the database. Exiting now...');
process.exit();
});
};
exports.login = (req, res, next) => {
passport.authenticate('local-login', {
successRedirect: '/start', // redirect to the secure profile section
failureRedirect: '/login', // redirect back to the signup page if there is an error
failureFlash: true // allow flash messages
})(req, res, next);
};
Example of a model user.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt-nodejs');
const Company = require('../models/company.js');
// define the schema for our user model
const userSchema = mongoose.Schema({
local : {
name : {
type: String,
required : true
},
email : {
type : String,
unique : true,
required : true
},
password : String,
active : Boolean,
company : {
type: mongoose.Schema.Types.ObjectId,
ref: 'Company'
}
}
});
// generating a hash for password
userSchema.methods.generateHash = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
};
// checking if password is valid
userSchema.methods.validPassword = function(password) {
return bcrypt.compareSync(password, this.local.password);
};
// create the model for users and expose it to our app
module.exports = mongoose.model('User', userSchema);
So, for the ones who finds themselves in the same spot:
After reviewing my app and the data it will keep I came to the conclusion that there is no need for splitting multi-tenancy. I reworked the app so when the user fetch or write data they only touch "their" data, and this is controlled backend.
But, I did make a post on mongoose github and got an answer,
See post here: https://github.com/Automattic/mongoose/issues/7386
The author gave a great length which seems to have an actually quite nice implementation of this with express and mongoose: http://nmajor.com/posts/multi-tenancy-with-expressmongoose
I hope this is of any help for you, and if you manage to find a solution or something, where you can show some simple code, please post it as there seems to be a lot of people asking about this.
Cheers.
I recently move in NodeJs from PHP and developing a project in MEANJS. But i unable to use a controller method in other controller. I think that i have followed wrong pattern.
student.model.js
-----------------
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var studentSchema = new Schema({
....
....
})
student.controller.js
---------------------
var Student = require('../models/student.model');
module.exports.get = function(req, res, next) {
var where={};
if(req.body.hasOwnproperty('id')){
where._id=req.body.id;
}
....
....
Student.find(where)
.populate({ path: 'createdBy', select: '_id name' })
.exec(function(err, studentData) {
if (err)
return res.status(500).end(err.message);
res.status(200).json(studentData);
})
}
report.controller.js
---------------------
var StudentCtrl = require('../controller/student.controller');
module.exports.getStudentGrade = function(req, res, next) {
//HERE I WANT get StudentCtrl.get data then response to client
//somethings like----------------
StudentCtrl.get(req,res,next){
//get studentData here
//manipulation on studentData
res.status(200).json(myReportData);
}
//-------------------
}
Make 2 versions on student.controller.get, for example student.controller.getCallback which receives a callback which you can then use in report.controller.js
student.controller.js
---------------------
var Student = require('../models/student.model');
module.exports.get = function(req, res, next) {
var where={};
if(req.body.hasOwnproperty('id')){
where._id=req.body.id;
}
....
....
Student.find(where)
.populate({ path: 'createdBy', select: '_id name' })
.exec(function(err, studentData) {
if (err)
return res.status(500).end(err.message);
res.status(200).json(studentData);
})
}
module.exports.getCallback = function(req, callback) {
var where={};
if(req.body.hasOwnproperty('id')){
where._id=req.body.id;
}
....
....
Student.find(where)
.populate({ path: 'createdBy', select: '_id name' })
.exec(callback);
}
report.controller.js
---------------------
var StudentCtrl = require('../controller/student.controller');
module.exports.getStudentGrade = function(req, res, next) {
//HERE I WANT get StudentCtrl.get data then response to client
//somethings like----------------
StudentCtrl.getCallback(req, function(err, myReportData) {
//get studentData here
//manipulation on studentData
if (err)
return res.status(500).end(err.message);
res.status(200).json(myReportData);
});
}
MEAN Stack is a complete JavaScript framework, it is a mixed of Mango dB, Express JS, Angular JS and Node JS. here Node JS play the role of server-side programming and npm server, so if you are re-forming the framework it makes into you have to independently connect MangodB, Express JS, Angular JS to PHP. please refer the link http://meanjs.org/
Please follow these steps:
mongo
index.js
models
user.js
client.js
controllers
user.js
client.js
Now
in models put all the schemas
and in controller call relevant schemas and function like save() update etc
and in the last all the controller method access it in the index hs
When i'm getting to my routes and requesting to getUSers from my mongoDB it says the User.find() is not defined. Sorry in advance if i use incorrect terminology i'm jumping in face first.
I'm assuming my routing is done incorrectly somewhere or i didn't include one file somewhere I'm hoping ya'll can help me determine if i'm either storing a file incorrectly in my structure, calling a file at the wrong time, or not initializing a variable correctly? Thanks for the help in advance.
Do i need an additional plugin to read and write to the database?
I keep getting the the following error it says usercontroller.js:20
Error: <!DOCTYPE html><html><head><title></title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>undefined is not a function</h1><h2></h2><pre>TypeError: undefined is not a function
at getUsers (c:\Users\Ravenous\kitchen\routes\user_api.js:5:10)
at c:\Users\Ravenous\kitchen\routes\user_api.js:26:3
file structure in case it helps
-bin
-node_modules-\
-user-app-\
-user.js //this is the model written with mongoose schema
-public-\
-html
-images
-javascripts-\
-userController
-userService //AngularJS factory
-stylesheets
-index.html
-routes-\
-user_api.js //with other useful routes inside.
-views //has some jade view engines that came with express-generator
-app.js
-package.JSON
I have this for the user model -- file: node_modules/user-app/user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
user_name: String,
password: String,
email: String,
location: String,
date_created : {type: Date, default: Date.now}
});
var User = mongoose.model('User', UserSchema);
module.exports= {User:User};
I then import user.js file to the ./routes/user_api.js file which looks like this
user_api.js :
var User = require('./node_modules/user-app/user');
function getUsers(res){
User.find().populate('users').exec(function(err, users){
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err){
res.send(err)
}else{
console.log(users[0][0].name)
res.json(users); // return all users in JSON format
db.close();
}
})
};
module.exports = function(app) {
// api -----------------------------------------------------------
// get all users
app.get('/node_modules/user-app/user', function(req, res) {
// use mongoose to get all users in the database
getUsers(res);
});
// create user and send back all users after creation
app.post('/node_modules/user-app/user', function(req, res) {
// create a user, information comes from AJAX request from Angular
User.create({
user_name: User.user_name,
password: User.password,
email: User.email,
location: User.location,
done : false
}, function(err, todo) {
if (err){
res.send(err);
}else{
// get and return all the users after creating one
getUsers(res);
}
});
});
// delete a user
app.delete('/node_modules/user-app/user:user_id', function(req, res) {
User.remove({
_id : req.params.user_id
}, function(err, user) {
if (err)
res.send(err);
getUsers(res);
});
});
};
I'm adding this user_api route and get method to the app.js file like so
// loading some required modules above this
var app = express();
var user = require('./routes/user_api')(app);
to handle the Angular and Node connection and state sharing i'm using the following
userController.js:
(function(){
'use strict'
var userCtrl = angular.module("userController",[]);
console.log('userController init')
userCtrl.controller('UserController', ['$scope','$http','Users',function($scope,$http,Users){
$scope.users = {};
$scope.loading = true;
console.log ("user init");
Users.get()
.success(function(data){
$scope.users = data;
$scope.loading = false;
console.log(data)
})
.error(function(err){
console.log('Error: ' + err);
});
$scope.createUser = function(){
if($scope.users.user_name != false){
console.log($scope.users.user_name)
$scope.loading = true;
Users.create($scope.users)
.success(function(data){
$scope.loading=false;
$scope.users = data;
console.log(data);
})
.error(function(err){
console.log('Error: ' + err);
});
}
};
}]);
})();
Change the line where you require User to
var User = require('./node_modules/user-app/user').User;
This is because in your export statement when you define a user you have the line:
module.exports = {User:User};
So, you are exporting an object that has a User property on it.
I am very new to nodejs and am not able to figure out what exactly is going on here-
i have a basic login page, in which as the user types in the values, i go to the home page, before which i check up on the database if that username exists or not. The problem i am having is that when i click on the submit button, the code never seems to reach the database function.
This is my module in app.js -
app.post('/home',function(req,res){
//check for user existence....
var str;
console.log("in home");
user_login.perform_login(req.body.username,function(err,str){
if(!err){
console.log(str+" in login");
var cookie_val=req.body.username;
res.cookie('username',cookie_val,{signed: true});
req.session.username=cookie_val;
res.render('home.ejs',{
layout: false,
locals: {varname: cookie_val},
udata: req.session.username
});
}
else{
console.log("Couldn't find it.");
res.redirect("/login");
}
});
});
This is the perform_login from user_login.js-
var mongo_db=require("./testdb.js");
exports.perform_login=function (username,callback){
mongo_db.getInfo(username,function(err,bundle){
if(!err){
//console.log("success\n"+bundle);
callback(false,bundle);
}
else{
//console.log("couldn't find it");
callback(true,null);
}
});
}
and this is the testdb.js-
var mongoose=require('mongoose');
mongoose.connect('mongodb://localhost/test');
exports.getInfo=function(value,callback){
var db=mongoose.connection;
db.on('error',console.error.bind(console,'connection error:'));
db.once('open',function(){
console.log("Connected!");
var userSchema=mongoose.Schema({
username: String,
password: String
});
var userInstances=mongoose.model('userInstances',userSchema);
userInstances.findOne({username: value},'username password',function(err,ui){
if(!err){
callback(false,ui);
}
else{
callback(true,"error");
}
});//findone
});//db.once function
}//getinfo
In the terminal i only get -"in home", after which nothing happens at all.In the browser, it seems to be processing but remains in the login page.
when i run the perform_login with an actual hard-coded value instead of req.body.username, immediately as app.js is launched, i get the proper results. So i am able to access the database somehow outside app.post().
Is there something wrong in the callbacks??
I think that you are doing a bit too much here. The symptoms you are describing are in my experience from a not connected mongoose. You do not need to manage the connection and listen on events, if it is connected. Mongoose handles this for you. You can query a model and it will return the result as soon the connection is established.
Here is an example that should work:
app.js
//initialize mongo connection
var mongooseConnection = mongoose.connect("mongodb://localhost/test");
user.js
var mongoose = require('mongoose');
var userSchema=mongoose.Schema({
username: String,
password: String
});
userSchema.statics.performLogin = function(username, callback) {
this.findOne({username: value},'username password',function(err,user){
if(!err){
callback(false,user);
}
else{
callback(true,"error");
}
});
module.exports = mongoose.model('users',userSchema);
route:
var User = require("./user");
app.post('/home',function(req,res){
User.performLogin(req.body.username, function (err, user) {
...
});
});