I'm attempting to make it so that when a player gets a highscore it searches there name, then it adds that highscore to there account. My issue is I don't know how to search for a name and update a tag using mongoose?
Here is my server code:
var mongoose = require("mongoose");
var bodyParser = require("body-parser");
var express = require("express");
var app = express();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
var PORT = 3332;
app.use("/", express.static(__dirname));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
mongoose.connect("mongodb://localhost/endg", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
var db = mongoose.connection;
db.once("open", function (cb) {
console.log("connection established");
});
io.on("connection", function (socket) {
console.log("user connected");
socket.on("chooseName", function (newName) {
var data = {
nickname: newName,
highscore: 0,
};
db.collection("dat").findOne({ nickname: data.nickname }, function (
err,
doc
) {
if (err) throw err;
if (doc) {
io.emit("nnTaken", null);
} else {
db.collection("dat").insertOne(data, function (err, coll) {
if (err) throw err;
console.log("rec estab");
io.emit("newNickname", null);
});
}
});
});
socket.on("player", function (player) {
socket.on("highscore", function (hs) {
console.log(player + ": " + hs);
db.collection("dat").updateOne(
{ name: player },
{ $set: { highscore: hs } }
);
//This is where im trying to update but the above code does not work
});
});
});
http.listen(PORT, function () {
console.log("server is up and running using port " + PORT);
});
How would i do this? I try using the update inside the highscore socket, so that when a highscore is achieved it updates that field but nothing is changing.
Or if you prefer async function with es6
socket.on('highscore', async highscore => {
await db.collection('dat').findOneAndUpdate(
{ nickname: player },
{ $set: { highscore: hs } }
)
});
I'm using ES6 Javascript syntax. highscore => {} is the same as function (highscore)
Also I'm using async function. await means the program wait until the function is done
I actually figured it out. I'll post the answer in case anyone has this issue in the future.
var mongoose = require("mongoose");
var bodyParser = require("body-parser");
var express = require("express");
var app = express();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
var PORT = 3332;
app.use("/", express.static(__dirname));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
mongoose.connect("mongodb://localhost/endg", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
var db = mongoose.connection;
db.once("open", function (cb) {
console.log("connection established");
});
io.on("connection", function (socket) {
console.log("user connected");
socket.on("chooseName", function (newName) {
var data = {
nickname: newName,
highscore: 0,
};
db.collection("dat").findOne({ nickname: data.nickname }, function (
err,
doc
) {
if (err) throw err;
if (doc) {
io.emit("nnTaken", null);
} else {
db.collection("dat").insertOne(data, function (err, coll) {
if (err) throw err;
console.log("rec estab");
io.emit("newNickname", null);
});
}
});
});
socket.on("player", function (player) {
socket.on("highscore", function (hs) {
console.log(player + ": " + hs);
db.collection("dat").findOne({ nickname: player }, function () {
db.collection("dat").updateOne(
{ nickname: player },
{ $set: { highscore: hs } }
);
});
});
});
});
http.listen(PORT, function () {
console.log("server is up and running using port " + PORT);
});
I went ahead and basically used findOne to find the players name, and then used updateOne with the $set to update the highscore value.
I'm guessing the issue was stemming from the fact that mongo wasn't able to tell which value i was trying to update.
Related
I'm trying to learn how to use the MERN stack. I've been following a YouTube tutorial (https://www.youtube.com/watch?v=WT67-OETeGU). Currently, I've defined and created my server.js file as follows:
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const cors = require("cors");
const mongoose = require("mongoose");
const todoRoutes = express.Router();
const PORT = 4000;
let Todo = require("./todo.model.js");
app.use(cors());
app.use(bodyParser.json());
mongoose.connect("mongodb://127.0.0.1:27017/todos", {
useUnifiedTopology: true,
useNewUrlParser: true
});
const connection = mongoose.connection;
todoRoutes.route("/").get(function(req, res) {
Todo.find(function(err, todos) {
if (err) {
console.log("error getting data");
} else {
res.json(todos);
}
});
});
todoRoutes.route("/:id").get(function(req, res) {
let id = req.params.id;
Todo.findById(id, function(err, todo) {
if (err) {
console.log("error finding todo object with id: " + id);
} else {
res.json(todo);
}
});
});
todoRoutes.route("/add").post(function(req, res) {
let todo = new Todo(req.body);
todo
.save()
.then(todo => {
res.status(200).json({ todo: "Todo added successfully" });
})
.catch(err => {
res.status(400).send("failed to save new todo");
});
});
todoRoutes.route("/update/:id").post(function(req, res) {
let id = req.params.id;
Todo.findById(id, function(err, todo) {
if (!todo) {
res.status(400).send("cant update id: " + id);
} else {
todo.todo_description = req.body.todo_description;
todo.todo_responsible = req.body.todo_responsible;
todo.todo_priority = req.body.todo_priority;
todo.todo_completed = req.body.todo_completed;
todo
.save()
.then(todo => {
res.json("Todo updated");
})
.catch(err => res.status(400).send("update not possible"));
}
});
});
app.use("./todos", todoRoutes);
I am trying to test my API out, so I installed Postman and set it up. I'm trying to make a GET request to: http://localhost:4000/todos. However, Postman only returns a 404, saying "Could not get any response".
I've run the commands mongod and mongo on my terminal to get Mongo running.
Any suggestions on where I've gone wrong?
It seems you are setting your endpoints as relative paths. Can you remove the dot proceeding "/todos"? in app.use("./todos", todoRoutes);
`
I currently implemented login and membership functions using Express & MySQL.
And I want to add JWT.
I wanted to create an API only through Postman, not on the Web, and I heard that I had to use Passport to search.
And I know there is also Express-generate, but I want to modify my current code.
I am a beginner in Node.js and want a guide.
app.js
var express = require('express');
var http = require('http');
var static = require('serve-static');
var path = require('path');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var expressErrorHandler = require('express-error-handler');
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit:10,
host:'localhost',
user:'root',
password:'password',
database:'test',
debug:false
});
var app = express();
app.set('port', 3000);
app.use('/public', static(path.join(__dirname, 'public')));
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(expressSession({
secret:'my key',
resave: true,
saveUninitialized:true
}));
var router = express.Router();
router.route('/process/login').post(function(req, res) {
console.log('/process/login');
var paramId = req.body.id;
var paramPassword = req.body.password;
console.log('request parameter:' + paramId + paramPassword);
authUser(paramId, paramPassword, function(err, rows) {
if (err) {
console.log('error');
res.writeHead(200, '{"Content-Type":"text/plain; charset=utf-8"}');
res.write('<h1>error</h1>');
red.end();
return;
}
if (rows) {
console.dir(rows);
res.writeHead(200, '{"Content-Type":"text/plain; charset=utf-8"}');
res.write('<h1>user login success</h1>');
res.write('<div><p>user:' + rows[0].id + ' </p></div>');
res.end();
} else {
res.writeHead(200, '{"Content-Type":"text/plain; charset=utf-8"}');
res.write('<h1>user not found</h1>');
res.end();
}
});
});
router.route('/process/adduser').post(function(req, res) {
console.log('/process/adduser');
var paramId = req.body.id;
var paramPassword = req.body.password;
console.log('request parameter' + paramId + paramPassword);
addUser(paramId, paramPassword, function(err, addedUser) {
if (err) {
console.log('error');
res.writeHead(200, '{"Content-Type":"text/plain; charset=utf-8"}');
res.write('<h1>error</h1>');
red.end();
return;
}
if (addedUser) {
console.dir(addedUser);
res.writeHead(200, '{"Content-Type":"text/plain; charset=utf-8"}');
res.write('<h1>user added</h1>');
res.end();
} else {
res.writeHead(200, '{"Content-Type":"text/plain; charset=utf-8"}');
res.write('<h1>user added fail</h1>');
res.end();
}
});
})
app.use('/', router);
var addUser = function(id, password, callback) {
console.log('addUser');
pool.getConnection(function(err, conn) {
if(err) {
if (conn) {
conn.release();
}
callback(err, null);
return;
}
console.log('db threadid' + conn.threadId);
var data = {id:id, password:password};
var exec = conn.query('insert into users set ?', data,
function(err , result) {
conn.release();
console.log('SQL syntax' + exec.sql);
if (err) {
console.log('SQL error;');
callback(err, null);
return;
}
callback(null, result);
});
});
};
var authUser = function(id, password, callback) {
console.log('authUser' + id + password);
pool.getConnection(function(err, conn) {
if (err) {
if (conn) {
conn.release();
}
callback(err, null);
return;
}
console.log('db threadid:'+ conn.threadId);
var tablename = 'users';
var columns = ['id'];
var exec = conn.query('select ?? from ?? where id = ? and password = ?', [columns, tablename, id, password],
function(err, rows) {
conn.release();
console.log('SQL syntax' + exec.sql);
if (err) {
callback(err, null);
return;
}
if (rows.length >0 ) {
console.log('user find');
callback(null, rows);
} else {
console.log('user not found');
callback(null, null);
}
});
});
};
var errorHandler = expressErrorHandler({
static: {
'404' : './public/404.html'
}
});
app.use(expressErrorHandler.httpError(404));
app.use(errorHandler);
var server = http.createServer(app).listen(app.get('port'), function() {
console.log('server start' + app.get('port'));
});
Hi #yori If you want to create an API, first I will recommend parsing your data as JSON objects and thus eliminating all HTML tags in your code.
In order to use JWT for authentication, you will have to install the jsonwebtoken package as part of your project dependencies: https://www.npmjs.com/package/jsonwebtoken
I will recommend following the in-depth instructions in this post as a guide: https://medium.freecodecamp.org/securing-node-js-restful-apis-with-json-web-tokens-9f811a92bb52
For scope though, here is some explanation:
Express can be used to build robust APIs which can be made available for consumption. POSTMAN is a GUI tool that developers use to query APIs. curl commands is the terminal alternative. JWT is a safe way of representating claims transfered between two parties. I see the need to break down these terms to you so that you will understand the need, relevance and difference between each tool.
Following the guide in the article you will have to refactor your code a little bit.
I have two file in my node js app server.js and database.js
//server.js
var db = require('./database.js');
var express = require('express');
var app = express();
var server = app.listen(8081, '000.00.00.000',function(){
var host = server.address().address;
var port = server.address().port
console.log('App listening');
})
app.get('/',function(req,res){
res.end("Hello Jamian");
})
app.get('/insertuser',function(req,res){
console.log("insert user called")
var result = new db.insertUser();
console.log("result " + result)
});
and
//database.js
var mysql = require('mysql');
var con = mysql.createConnection({
host:"localhost",
user:"0000",
password:"0000",
database: "aaaa"
});
con.connect(function(err){
if(err) throw err;
console.log("DB Connected");
});
module.exports = {
insertUser: function () {
console.log("module exported");
var SQL_insert_user = "insert into users(username,useremail,usermobile,userpassword,activetoken) values('darren','darren#yahoo.in','980000000','password','ASKDO5615F')";
con.query(SQL_insert_user,function(err,result){
if(err) throw err;
console.log("data inserted");
return result;
});
},
bar: function () {
console.log("bar called")
}
};
I need a callback from the insertUser function in database.js so i can call a res.end("data inserted"). however it seems con.query is going async, hence I am getting a blank value when I try to log result in server.js from get/insertuser in server.js
data inserted
insert user called
module exported
result {}
data inserted
Use promises. Either native or from a library.
Here's how you could do it with a promise:
insertUser: function(){
return new Promise(function(reject, resolve){
var SQL_insert_user = "insert into users(username,useremail,usermobile,userpassword,activetoken) values('darren','darren#yahoo.in','980000000','password','ASKDO5615F')";
con.query(SQL_insert_user,function(err,result){
if(err) reject(err);
else resolve(result);
});
});
},
Then you can use it your other file like this:
insertUser()
.then(function(result){
// do something with the result
})
.catch(function(err){
// Oh no! there was an error!
});
in your server js do
app.get('/insertuser',function(req,res){
console.log("insert user called")
var result = new db.insertUser(function(result) {
console.log("result " + result)
});
});
and in your database do
module.exports = {
insertUser: function (cb) {
console.log("module exported");
var SQL_insert_user = "insert into users(username,useremail,usermobile,userpassword,activetoken) values('darren','darren#yahoo.in','980000000','password','ASKDO5615F')";
con.query(SQL_insert_user,function(err,result){
if(err) throw err;
console.log("data inserted");
cb(result);
});
},
bar: function () {
console.log("bar called")
}
};
I'm looking to change requestHandler.value to 5 for my functional styled tests.
When running the suite, creating 1000 documents in the db is not really an option, so is it possible to change it's value programmatically before running the suite and then reset it afterwards? I can create 5 documents in db before the test to work with.
Of coarse I can stub countDocumentsInDb() in unit tests to return what I need, but I've simplified logic below for the sake of the question.
app.js:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var requestHandler = require('./lib/requestHandler.js');
var PORT = 4000;
app.route('/validate')
.get(function(req, res) {
requestHandler.process(req, res);
});
if (!module.parent) {
server.listen(PORT, function(err) {
if (err) {
return;
}
});
}
module.exports = app;
requestHandler.js:
var requestHandler = {
value: 1000,
process: function(req, res) {
numberOfDocumentsInDb = countDocumentsInDb();
if (numberOfDocumentsInDb === this.value) {
res.send(true);
} else {
res.send(false);
}
}
};
module.exports = requestHandler;
FVT style test ..
var Promise = require('promise');
var request = require('supertest');
var chai = require('chai');
chai.should();
var server = require('../../app.js');
describe('app.js', function() {
describe('/validate', function() {
it('should return true if number of documents in db matches pre-defined value', function(done) {
var fvtPromise = new Promise(function(fulfill) {
request(server)
.get('/validate')
.expect(200)
.end(function(err, res) {
if (err) {
throw err;
}
res.body.should.equal(true);
fulfill(null);
});
});
fvtPromise.done(function() {
done();
});
});
});
});
You can play with the require.cache, that will allow you to modify the values of requestHandler.
Is just an example I hope you get the idea.
- In the before each modify the require cache and set your test values
-In the after each set back the original values
-Please notice that the const server = require('./app.js'); is inside the test, so it will take the cache vales
e.g.
describe('test with cache', function(){
require('./requestHandler');
let originalValues;
beforeEach(function() {
originalValues = require.cache[ require.resolve('./requestHandler') ].exports;
require.cache[ require.resolve('./requestHandler') ].exports = {
value:5,
process: function(req, res) {
//other stuff
}
};
});
afterEach(function() {
require.cache[ require.resolve('./requestHandler') ].exports = originalValues;
});
it('should pass', function(){
const server = require('./app.js');
var fvtPromise = new Promise(function(fulfill) {
request(server)
.get('/validate')
.expect(200)
.end(function(err, res) {
if (err) {
throw err;
}
res.body.should.equal(true);
fulfill(null);
});
});
fvtPromise.done(function() {
done();
});
expect(true).to.be.true;
});
});
I am trying to make a url shortener app using express. I have 2 middle wares for routes /shorten/:url* and /:code respectively. Somehow when I make requests like /shorten/iamarshad.com (requests that are not formatted and will fail my validateUrl method), middleware handling that request gets executed sometimes twice and sometime thrice. Why is this happening ?
Code for route.js:
var express = require("express");
var router = express.Router();
var crypto = require("./crypto");
var styles = "<style>#import url('https://fonts.googleapis.com/css?family=Cormorant+Garamond');" +
"body{background: #fefefe; word-wrap: break-word;}" +
"p {font-size: 30px;color: #b33c66;font-family: 'Cormorant Garamond', monospace;text-align: center;" +
"margin-top: 40vh;font-weight: 500;word-spacing: 2px;}</style>";
function verifyUrl(req, res, next) {
console.log("/shorten middleware called");
req.params.url += req.params[0];
console.log(req.params.url);
if (validateUrl(req.params.url)) {
req.db.collection("counter")
.find({_id: "counter"})
.toArray(function (err, docs) {
if (err) console.error("Error occurred while getting COUNTER document:", err);
req.encodedId = crypto.encode(docs[0].count);
next();
});
}
else {
var elem = "<p>Please enter correct and formatted url!</p>";
res.send(styles + elem);
}
}
function incrementCounter(req, res, next) {
// increasing counter
req.db.collection("counter")
.update(
{
_id: "counter"
},
{
$inc : {
count : 1
}
}
);
next();
}
function insertUrlDocument(req, res, next) {
//inserting new url document
var obj = {original_url: req.params.url, _id: req.encodedId, entry_time: new Date().toUTCString()};
req.db.collection("urls")
.insert(obj, function(err, data) {
if(err) console.error("Error happened while adding new document:", err);
});
next();
}
function sendResponse(req, res) {
var elem = "<p>" + JSON.stringify({'original_url': req.params.url, 'short_url': 'https://shorten-that.herokuapp.com/' + req.encodedId}) + "</p>";
res.send(styles + elem);
}
function validateUrl(url) {
var format = /(http:\/\/|https:\/\/)[a-z0-9\-]+[.]\w+/;
return (format.test(url));
}
router.get("/:code", function(req, res) {
console.log("/:code middleware called with url", req.params.code);
var code = req.params.code.toString();
// searching short-url-id
req.db.collection("urls")
.find({_id: code})
.toArray(function(err, docs) {
if(err) console.error("Error occurred while searching urls:", err);
console.log(docs);
if(docs.length > 0)
res.redirect(docs[0]["original_url"]);
else {
var elem = "<p>Oops, wrong url requested!</p>";
res.send(styles + elem);
}
});
});
// better solution needed
router.get("/shorten/:url*", [verifyUrl, incrementCounter, insertUrlDocument, sendResponse]);
module.exports = router;
Code for server.js:
var express = require("express")
, mongo = require("mongodb").MongoClient
, port = process.env.PORT || 8080
, path = require("path")
, routes = require("./routes")
, favicon = require("serve-favicon");
var app = express();
app.use(favicon(path.join(__dirname, 'public','favicon.png')));
app.use(express.static(path.join(__dirname, "public")));
var url = 'mongodb://localhost:27017/url-shortener';
mongo.connect(url, function(err, db) {
if (err) console.error("Error occurred while connecting to db:", err);
console.log("successfully connected to db.");
app.use(function(req, res, next) {
req.db = db;
next();
});
app.use("/", routes);
});
app.listen(port, function() {
console.log("App running on", port);
});