RestAPI's deleting a model with another model - javascript

EDIT: I've just been informed by my professor not to access the driver from within the admin. Should be inside driver only.
I'm working on a project using restAPI's and a requirement is that an admin can delete driver.
They each both have their own schema and model in their own .js file
var mongoose = require('mongoose');
var AdminSchema = new mongoose.Schema({
name: String
});
mongoose.model('Admin', AdminSchema); // Model name is 'Admin'
module.exports = mongoose.model('Admin'); // Export for use in other parts of program
Similarly for the driver...
I'm using Postman to test all of this,
Now i'm stuck trying to have my admin be able to delete from both the admin database and the driver database using their ID's
the DELETE method for the admin looks like:
var Admin = require('./Admin');
var Driver = require('./Driver');
.
.
.
router.delete('/:id', function (req, res) {
Admin.findByIdAndRemove(req.params.id, function (err, admin) {
if (err) return res.status(500).send("There was a problem deleting the admin.");
res.status(200).send("Admin: " + admin.name + " was deleted.");
});
});
I've tried many things, including the method looking like this
router.delete('/:id', function (req, res) {
Admin.findByIdAndRemove(req.params.id, function (err, admin) {
if (err) return res.status(500).send("There was a problem deleting the admin.");
res.status(200).send("Admin: " + admin.name + " was deleted.");
});
Driver.findByIdAndRemove(req.params.id, function (err, driver) {
if (err) return res.status(500).send("There was a problem deleting the driver.");
res.status(200).send("Driver: " + driver.name + " was deleted.");
});
});
But this doesn't work, and I've tried having the methods separately, but the program only looks for whichever one is first, so if I have the method to delete the driver before the admin's delete method, it will find drivers, but not admins. It simply triggers the driver's error message and doesn't trigger the admins delete method.
Any tips or suggestions would be greatly appreciated. This is my first time learning about this stuff, and it's very interesting, but it's quite tricky!
Thanks!

The way you call the DB queries is incorrect. Both calls Admin.findByIdAndRemove and Driver.findByIdAndRemove are asynchronous so you need to treat them as such. You also can't call res.status(200).send(.. twice from the route handler. It should cause an error "Can't send headers after they were already sent" or something like that.
One way could be:
router.delete('/:id', function (req, res) {
var response = '';
Driver.findByIdAndRemove(req.params.id, function (err, driver) {
if (err)
response += "There was a problem deleting the driver.";
else
response += "Driver: " + driver.name + " was deleted.";
Admin.findByIdAndRemove(req.params.id, function (err, admin) {
if (err)
response += "There was a problem deleting the admin.";
else
response += ("Admin: " + admin.name + " was deleted.";
// you can't use error status since both db results could be different
res.status(200).send(response);
});
});
});
Also note that making multiple queries makes it difficult to use corect http status since each db query could have diferent result
Better way would be to have 2 routes one for admin and the other for driver
router.delete('/driver/:id', function (req, res) {
Driver.findByIdAndRemove(req.params.id, function (err, driver) {
if (err) return res.status(500).send("There was a problem deleting the driver.");
res.status(200).send("Driver: " + driver.name + " was deleted.");
});
});
router.delete('/admin/:id', function (req, res) {
Admin.findByIdAndRemove(req.params.id, function (err, admin) {
if (err) return res.status(500).send("There was a problem deleting the admin.");
res.status(200).send("Admin: " + admin.name + " was deleted.");
});
});

Related

How to redirect from a mysql query in node.js webapp?

I'm making a simple node.js webapp for inserting data into a database with a condition - when there's two instances with the same time attribute, the insert query isn't called and you get redirected to a simple html page with a message that you have to pick another time.
My question is, how can I redirect from a block of code belonging to query? or is there another way to let user know that he has to pick another time?
app.post('/', function(req, resp) {
try {
var name = req.body.name;
var date = req.body.date + " " + req.body.time;
var phone = req.body.phone;
var spz = req.body.spz;
var typeOfProblem = req.body.typeOfProblem;
con.query(("SELECT COUNT(*) AS datecheck FROM `objednani` WHERE datetime = '"+ date +"'"), function(err, result){
if (err) throw err;
if(result[0].datecheck > 1){
console.log("preplneno"); // THIS IS THE POINT WHERE I WANT TO REDIRECT THE USER
} else {
con.query(("INSERT INTO objednani (name, datetime, phone, spz, typeofproblem) " + "VALUES ('"+name+"','"+date+"','"+phone+"','"+spz+"','"+typeOfProblem+"')"), function (err, result) {
if (err) throw err;
console.log("uspech");
});
}
});
} catch (err) {
resp.redirect('/fail');
}
});
You can call resp.redirect('/fail'); inside your query block, or anywhere in function(req, resp) function. You don't need to throw and catch.
As another suggestion: you can try parameter embedding for your sqls. otherwise you can be subject to sql injection attacks.

Node.js - How do I use a complex function in HTML like "addUser"

I was given an assignment in class for making a basic ReSTFul Web Application, and received a sample to create mine off of, but only 2 of the 4 routes worked and I'm very new so I can't figure out why the other functions aren't working. The code looks like:
//setup
var express = require('express');
var app = express();
var fs = require("fs");
//run the server
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
//http://localhost:8081
//general route
//data for existing users located in "users.json"
//here is the refer
app.get("/", function(req,res){
var msg=""
msg += "<center><h1> This is the default page </h1></center>"
msg += " use the following <br />"
msg += " http://localhost:8081/listUsers <br />"
msg += " http://localhost:8081/addUser <br />"
msg += " http://localhost:8081/deleteUser <br />"
msg += " http://localhost:8081/(Put id# here) <br />"
res.send(msg);
});
//To find a list of users
app.get('/listUsers', function (req, res) {
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
console.log( data );
res.end( data );
});
})
//To add a user to the list
var user = {
"user4" : {
"name" : "mohit",
"password" : "password4",
"profession" : "teacher",
"id": 4
}
}
app.post('/addUser', function (req, res) {
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
//First read existing users.
data = JSON.parse( data );
data["user4"] = user["user4"];
console.log( data );
res.end( JSON.stringify(data));
});
})
//to show details of user by id#
app.get('/:id', function (req, res) {
// First read existing users.
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
var users = JSON.parse( data );
var user = users["user" + req.params.id]
console.log( user );
res.end( JSON.stringify(user));
});
})
var id = 2;
//to delete a user
app.delete('/deleteUser', function (req, res) {
// First read existing users.
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
data = JSON.parse( data );
delete data["user" + 2];
console.log( data );
res.end( JSON.stringify(data));
});
})
The functions for listing users and specifying users work, but the addUser and deleteUser say "unspecified," leading me to believe that the ( data ) part may not be properly specified. But I don't know specifically how I would specify a function.
Okay, there are a few issues going on here. First of all, it helps to walk through your code line by line to see what its doing, so you can try to figure out what you're missing:
You're reading the contents of users.json as a string using fs.readFile, which gets put in the variable "data" in your callback function.
You're converting "data" from a string to an object using JSON.parse. So far, so good.
You're setting the property "user4" on data, which should now be a list of users. This may or may not be correct depending on what the structure is for your users - if its an array, this code won't work. If its an object where each key is the username, you'll be fine here. Also, potential problem - you're setting the same key on the data object every time this request is made. You will continually overwrite the "user4" property each time, which will act as an update instead of an add. There's no way to determine what this code should be without see what you're POSTing into this API.
You're setting data["user4"] equal to user["user4"], or more specifically the value of the "user4" property of user. First issue - user is not defined anywhere. If this was data that was sent in the body of the POST, you'll want to read it from the body - probably something like (again, dependent on the format of data you're sending during your POST):
data["user4"] = req.body.user;
You're logging the full list of users. No problem here, good for visibility while debugging.
You're sending back the list of users you read from the file, plus the single user you just added.
There's a step missing here - you never saved the updated list of users in any way. Some type of data should be returned to the user, but the next time you call add or get (or any other method), the user you just defined won't be present, since it was never added to users.json. Here's a great post on how to write a string to a file: Writing files in Node.js
It will probably end up looking like this:
fs.readFile( __dirname + "/" + "users.json", 'utf8', function (err, data) {
//First read existing users.
data = JSON.parse( data );
data["user4"] = user["user4"];
console.log( data );
// Convert your updated user object into a JSON string
var strData = JSON.stringify(data);
// Write the updated JSON string out to the file
fs.writeFile(__dirname + "/" + "users.json", strData, function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
});
res.end( JSON.stringify(data));
});
This covers the addUser endpoint, but you'll need to introduce similar changes for your deleteUser endpoint. If you're having trouble past this point, I'd recommend adding the contents of users.json to your question, as well as adding more detail on what you get back when you make the call into addUser and deleteUser (you can view the response body in Chrome dev tools -> Network tab).

get count collection with socket.io-mongodb

I'm trying to make a simple task.
In the first place, on client side, i'm sending data to server and then i insert these data into my mongodb database.
Then i try to get count of clients from my database.
var express = require('express');
var MONGO_URL = "mongodb://localhost:27017/mydatabase";
var app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server),
mongo = require('mongodb').MongoClient,
fs = require('fs');
var countUserSuscribed =0;
//here i insert data
/* Connection events */
io.on('connection', function (client) {
console.log("User connected");
client.on('InsertNewUser', function (newUser) {
console.log("we ar in InsertNewUser event");
//////////////////////////////////////////////////////////
mongo.connect(MONGO_URL, function (err, db) {
console.log("we are connected to mongodb");
var Users = db.collection('User');
console.log("on crée la collection et on fait l'ajout");
Users.insert({ player: myP }, function (err, o) {
if (err) { console.warn(err.message); }
else { console.log("user inserted into db: user"); }
});
});
})
});
//GET COUNT USER
console.log("here we get count user");
mongo.connect(MONGO_URL, function (err, db) {
countUserSuscribed = Users.count();
console.log("we got " + countUserSuscribed + " user in mongoDB");
});
With this code i can create collections and insert documents but the count function doesn't work and i didn't find much explanations on npm documentation.
Is it possible to use others mongodb functions than insert and collection with socket.io-mongodb ?
If it is, can someone give an example or explain me how to use it?
The count function works but is async function and takes a callback.
here's the fix:
countUserSuscribed = Users.count(function (err,c) { console.log(c) });
https://www.npmjs.com/package/mongodb-autoincrement consider using that. It keeps a track of all inserted document. Plus it has a handy feature to get the next count. Example let's say you inserted two records. If you call next count it will show 3. There fore to get the total documents inserted call get next count - 1. Make sense?
Sorry here is the correct one. https://www.npmjs.com/package/mongoose-auto-increment

Nodejs callback with bad workflow

I'm new with NODE and I'm trying this code:
require('../../constants.js');
function dbConnect() {
var mysql = require('mysql');
var connection = mysql.createConnection({
host : DB_HOST,
database : DB_NAME,
user : DB_USER,
password : DB_PASS,
});
connection.connect(function(err) {
console.log("Database is connected ...");
});
return connection;
}
function dbDisconnect(connection) {
connection.end();
console.log("Closing DB Connection");
}
function findPlayer(surname) {
var connection = dbConnect();
console.log("Finding -> " + surname);
var query = 'SELECT * FROM players WHERE surname = "' + surname + '"';
connection.query(query, function(err, rows, fields)
{
if (err) throw err;
for (var i in rows) {
console.log('Players: ', rows[i].surname);
}
});
dbDisconnect(connection);
}
exports.findPlayer = findPlayer;
After that, I've a laucher file:
require('./constants.js');
var aar = require('./libs/DBManager.js')
console.log('Loading DBManager');
var player = aar.findPlayer('Potter');
console.log(player);
Correct workflow is:
Loading DBManager
Database is connected...
Finding -> Potter
Players: Potter
Closing DB Connection
However the result is:
Loading DBManager
Finding -> Potter
Closing DB Connection
undefined
Database is connected...
Players: Potter
What's my wrong? Is some callback issue?
You are closing your connection before your query is for sure done.
you should put the dbDisconnect(connection); after the end of the query but inside the callback.
connection.query(query, function(err, rows, fields)
{
if (err) throw err;
for (var i in rows) {
console.log('Players: ', rows[i].surname);
}
dbDisconnect(connection);
});
also the findPlayer is not returning anything, so the console.log(player); will be undefined
Javascript is Async in nature, it doesn't wait for I/O operations. Any network call including request to connect to a DB comes under I/O operations.
The problem is that you are requesting a DB connection and before it is returned, you are making call to get data for players. I suggest you pass a callback method to the
dbConnect(callback)
And in that callback, you pass the query or operation you want to execute:
Create a callback method that contains the code to retrieve the players information
Call dbConnect() to establish the connection to DB and pass the callback as an argument
After connection is established, execute the callback
After you are done, you can close the connection, but make sure the code to close the connection, is with in the callback and is executed only after you received the data from Db
On the contrary if you are comfortable with ORM, i suggest you try Sequelize, it abstracts out the requirement to create and disconnect connections with DB, so you can focus on your crud operations.

Using Async queue to control DB connection request

I'm buidling an app with Node anb Mongodb Native. I'm working on a db module which i can require and call in other modules so that I end up using just one connection. The module db.js started out with this code:
var _db = null;
var getDb = module.exports.getDb = function(callback) {
if (_db) {
console.log('_db returned');
return callback(null, _db);
}
MongoClient.connect('mongodb://localhost:' + config.db.port + '/' + config.db.name, {native_parser: true}, function (err, db) {
if (err) return callback(err);
console.log('_db created');
_db = db;
callback(err, _db);
});
};
In my other modules that need a db connection I do this
db.getDb(function (err, connection) {
// Do something with connection
});
It works fine. But an unpleasant problem is that if my code would call getDb multiple times in a very short time span, I would end up with several copies of a connection. Like if I do my db.js requirements and getDb calls at the very beginning of all modules that need a db connection
I'm now thinking about controlling the calls to getDb by queuing them, so that only the absolute first call will create a connection and save it in _db. All later calls will get the created connection _db in return. I believe Async queue will help me with this...
The problem is that i dont understand how I write this with Async queue. The documentation is a little bit vague, and i dont find any better examples online. Maybe you can give me some hints. This is what i got so far...
var dbCalls = async.queue(function (task, callback) {
if (_db) {
console.log('_db returned');
return callback(null, _db);
}
MongoClient.connect('mongodb://localhost:' + config.db.port + '/' + config.db.name, {native_parser: true}, function (err, db) {
if (err) return callback(err);
console.log('Connected to mongodb://localhost:' + config.db.port + '/' + config.db.name);
_db = db;
callback(null, _db);
});
}, 1);
// I guess this .push() must be the exposed (exported) API for other modules to get a connection, but how do I return it to them,
dbCalls.push(null, function (err) {
console.log('finished processing foo');
});
dbCalls.push(null, function (err) {
console.log('finished processing bar');
});
I dont understand the object passed as first argument to .push() What should i use if for? Right now its null How do I pass on the connection and possible error all the way out to the module that made the call?
A quick and dirty solution without async.queue:
var _db = null;
var _err = null;
var _queue = [];
var _pending = false;
var getDb = module.exports.getDb = function(callback) {
if (_err || _db) {
console.log('_db returned');
return callback(_err, _db);
} else if (_pending) { // already a connect() request pending
_queue.push(callback);
} else {
_pending = true;
_queue.push(callback);
MongoClient.connect(..., function (err, db) {
_err = err;
_db = db;
_queue.forEach(function(queuedCallback) {
queuedCallback(err, db);
});
});
};

Categories