Live username availability check in node express.js and client side js - javascript

I am making an express, MongoDB, and handlebars(templating engine) web app with a form that lets users create their unique username. Now I want to display a little tooltip after set intervals to display whether the username is available or not. The way I have done it is by exposing an endpoint with JSON data about usernames
api.get("/usernames", (req, res)=>{
users.find({}, (err, users)=>{
let out = []
users.forEach(user=>{
out.push(user.uname)
})
})
res.json({usernames: out})
})
And then I fetch the data and loop through the array on the client-side. But I don't think this method would scale very well. Is there an easier and more scalable way to achieve this??

try this
api.get("/usernames", (req, res)=>{
users.find({}, (err, users)=>{
let out = users.filter(x=>x.uname===req.body.name)
let result = out.length?"Already exists": "Available"
})
res.json({result: result})
})

Related

Is this a secure enough method to recover data?

I'd love to know if this method I'm using is secure enough to use on a public project, since I can't really find any other way to retrieve my id from my currently logged in user, but it's a fairly straightforward method , I find. If this method is not secure would it be possible to have a way to proceed? Thanks in advance.
I have a button for example when I use the send of the html that there is inside my div userid on the server to then use this information to make SQL queries from my app.js server.
I use socket.io hbs express node js jwt mysql
From my pages.js file generated with the express library where the main roads of my website are located, I send my user ID.
router.get('/accueil', authController.isLoggedIn, (req, res) => {
if(req.user) {
res.render('./accueil', {
data: req.user.id
});
} else {
res.redirect('/');
}
});
With Handlebars I display this data in my index.hbs (display: none;).
<div id="iduser">{{data}}</div>
Then I get my iduser div on my client.js
let userid = document.getElementById('iduser').innerHTML;
// (My method to display this div)
socket.on('uid', (data) => {
pargent.innerHTML = JSON.stringify(data.data[0].argent);
})
//
So I want to use this userid variable to make SQL queries from my app.js.
(let userid = document.getElementById('iduser').innerHTML;)
I am using socket.io for communication between client and server to send my userid data
Example :
db.query('UPDATE users SET money = money + ? WHERE id = ?', [100, theUserId]);
No
Never trust user supplied data.
References:
https://www.oreilly.com/library/view/http-developers-handbook/0672324547/0672324547_ch22lev1sec1.html
https://flylib.com/books/en/1.290.1.90/1/
https://www.garybell.co.uk/never-trust-user-input/
https://medium.com/#berniedurfee/never-trust-a-client-not-even-your-own-2de342723674
https://www.invicti.com/blog/web-security/input-validation-errors-root-of-all-evil/
https://laravel-news.com/never-trust-your-users
https://www.wearenova.co.uk/nova-blog/when-it-comes-to-online-security-why-you-should-never-trust-a-client
It depends on your authController.isLoggedIn logic,
But I would like to suggest an alternative solution simple as that;
iron-session
Read their docs, it's matches your use case and easy to use; here is equivalent of the snippet you provided with iron session:
//initiate session middleware yourself
router.use(session)
// later here
router.get('/accueil', (req, res) => {
if(req.session.user) {
res.render('./accueil', {
data: req.user.id
});
} else {
res.redirect('/');
}
});

How to declare a static array in Node.js?

I am trying to create a static array named "categories" whom I wish it will be initialized ONCE in my Node.js application. I mean, when I close the app and run it again - I want it to KEEP the state of the "categories" array.
What happens is that the array is initialized for each time I run this app. Though I want it to be declared only once in this app's lifetime.
router.post("/add_category", (req, res, next) => {
var category = req.body.category;
categories.push(category);
res.render("index", { categories });
});
The simplest solution is to just write the array to a file as JSON and then load that back in when your server starts.
let categories = require('./categories.json');
router.post("/add_category", (req, res, next) => {
var category = req.body.category;
categories.push(category);
fs.writeFile(`./categories.json`, JSON.stringify(categories), () => {
res.render("index", { categories });
});
});
Node.js, by itself, does not have any automatically persisted variables that get saved to disk by themselves and are automatically available the next time you run the program. You have to code that yourself.
You should need a database for that kind of data persistence. But at times, a full-blown database (MongoDB, SQL) could be considered overkill since you only need to save a simple array.
So, consider using the "node-persist" package, here's a possible solution:
const storage = require('node-persist');
storage.initSync();
storage.setItem('categories', [ . . . ] );
console.log(storage.getItem('categories'));
That is was databases are for. Consider Using some SQL or noSQL database that will store values even if server is reseted.

MERN Stack: Can ExpressJs route add data from one Model to another Model's array attribute?

I hope I worded that correctly. Let me explain.
I'm creating an app where users can organize tournaments for a game (separate).
I'm creating this app with the MERN stack, with Redux as well.
I have numerous routes defined, for CRUD functionality and user authentication for example. My current workflow is to create the backend route, test it with Postman, and once it works I create the Redux reducer/action.
I have two data models. One is User, and one is Tournament.
Tournament model has a bunch of String type attributes like 'title', and one of it's attributes is 'participants' which is Array type.
I'm trying to write a Post request to a tournament/:id that contains the User.username, and push() that into Tournament.participants array.
I have tried multiple things but my current code looks like
router.post('/:id', (req, res) => {
Tournament.findById(req.params.id)
.then(tournament => tournament.participants.push(req.body))
.catch(err => res.json(err))
});
I am lost and could use help. Thanks all
This could work I think:
router.post('/:id', (req, res) => {
Tournament.findById(req.params.id)
.then(tournament => {
tournament.participants.push(req.body)
// save the updated tournament to the DB and take advantage of Promise-chaining
return tournament.save()
})
// send a response to the client
.then(savedTournament => res.json(savedTournament))
.catch(err => res.json(err))
});
You just need to make sure you save the updated tournament to the DB with this line:
return tournament.save()
Then, that will return a Promise which you can chain and then send off a response if successful. You were pulling the Model from the DB and updating the participants array, but then you need to store it in the DB and send a response to the client.

Error with get request for users

When using a get request for all the users in my database (see code below) i only get the "first" user in the database. If i instead try to use the "findOne"-method i get the same user as before no matter what i put in (the username doesn't even have to be in the db it still gives me the same user). I've been trying to understand why this isn't working but can't find any problems with the code. Could it be a problem with db settings or something similar? All help is appreciated!
In AuthController:
// Get all users
AuthController.allusers = function(req, res) {
User.find({}, function(err, users) {
}).then(function(users) {
res.json({users: users});
});
}
In routes:
// GET Routes.
router.get('/users', AuthController.allusers);
Since you are using Sequelizejs, you might want to do findAll.
AuthController.allusers = function(req, res) {
User.findAll().then(function (users) {
res.send({users: users});
}
}
According to the docs:
find - Search for one specific element in the database
findAll - Search for multiple elements in the database

What does a Node.js web service look like?

I am taking a look at Node.js and thinking about using it for building an API. From what I can tell, ExpressJS would be the web framework and is not what I'd be looking for to solve this.
So what would a web service look like? Would it simply be creating a server, talking to mongo and returning results? Also, what does routing look like? (I'd obviously want to 'design' the routes).
If Express would be your web framework, look at the express-resource (Github) middleware for routing an API. You define resources and it'll wire up REST-style routing for you with very little boilerplate.
app.resource('horses', require('./routes/horses'), { format: json })
Given the above, express-resource will hook up all the REST-style routes to actions you supply, returning JSON by default. In routes/horses.js, you export actions for that resource, along the lines of:
exports.index = function index (req, res) {
// GET http://yourdomain.com/horses
res.send( MyHorseModel.getAll() )
}
exports.show = function show (req, res) {
// GET http://yourdomain.com/horses/seabiscuit
res.send( MyHorseModel.get(req.params.horse) )
}
exports.create = function create (req, res) {
// PUT http://yourdomain.com/horses
if (app.user.canWrite) {
MyHorseModel.put(req.body, function (ok) { res.send(ok) })
}
}
// ... etc
You can respond with different representations:
exports.show = {
json: function (req, res) {
// GET http://yourdomain/horses/seabiscuit.json
}
, xml: function (req, res) {
// GET http://yourdomain/horses/seabiscuit.xml
}
}
Middlewares like express-resource can make life with Node and Express much easier, take a look through the examples on github to see if it'll do what you need.
Here is a stub that looks up a horse name from a Postgres database and returns the result as JSON. Clients would access would access the API by going to address such as http://yourdomain.com/api/horse/seabiscuit
app.get('/api/horse/:name', function(req, res){
pg.connect(conString, function(err, client) {
var horse = req.params.name;
var sql = "...";
client.query(sql, function(err, result) {
if (err) {
...
}
for (var i=0; i<result.rows.length; i++) {
// Customize data as needed
}
return res.send(JSON.stringify(result.rows));
});
});
});
Node is pretty low level. It's like C in JavaScript's clothing. Since it's comparable to C, there's pretty much a lot you can do with Node. Creating web servers is just one of them. You can create live chat servers using sockets, blogs, streaming etc. The possibilities are infinite. You are limited only by your imagination.
Routing is just a task where you take in commands (commonly via URL or headers) and do tasks based on those commands passed.
But even I have not yet scathed the surface of node. It's API is huge and getting bigger. Better try using some basic library like Express or Connect first since they pretty much abstract the basic requirement of building the server from code.

Categories