Create multiple user login system with personal messages - javascript

I want to create a multi user login system with private messages.
I created the theory in JavaScript (just for sketching out the theory and functionalities), and I wonder if I am on the right track.
Of course I will change it to a backend language later on with all the validations, this is purely for sketching.
// User database simulation
var users = [];
var defaultUser = {
'rights': 1, /* 0 - 3: 0 is banned, 1 is default, 2 is moderator, 3 is admin */
'activated': false,
'createdAt': null,
'updatedAt': null,
'username': null,
'userId': null,
'email': null,
'pass': null, /* will be encrypted */
'profile': {
'sex': null,
'age': null,
'avatar': null,
'updatedAt': null,
},
'messages': {
'inbox': [],
'outbox': [],
'trash': [],
'drafts': []
}
};
var defaultMessage = {
'id': null,
'date': null,
'from': null,
'to': null,
'message': null
};
var userManagement = {
'register': function(username, email, pass){
var user = $.extend({}, defaultUser);
user.username = username;
user.email = email;
user.pass = pass;
user.userId = username + '_' + Math.floor(Date.now() / 1000);
// If everything is valid, register:
// User database insert simulation
users.push(user);
console.log('Registered', user);
},
'login': function(username, pass) {
// User database query simulation
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.username === username) {
if(user.pass === pass) {
console.log('Logged in', user);
} else {
console.log('Pass incorrect');
}
} else {
console.log('User not found');
}
}
},
'forgotUsername': function(email) {
// User database query simulation
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.email === email) {
console.log('username ['+ user.username +'] send to ' + user.email);
} else {
console.log('User not found');
}
}
},
'forgotPass': function(username) {
// User database query simulation
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.username === username) {
console.log('pass from user ['+ user.username +'] send to ' + user.email);
} else {
console.log('User not found');
}
}
},
'getUserById': function(userId){
var key;
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.userId === userId) {
return user;
}
}
return null;
},
'getUserByUsername': function(username){
for(var i = 0, l = users.length; i < l; i++) {
var user = users[i];
if(user.username === username) {
return user;
}
}
return null;
}
/* TODO: updateProfile, activate */
}
var message = {
'send': function(fromUserId, toUserId, msg){
var sender = userManagement.getUserById(fromUserId);
var receiver = userManagement.getUserById(toUserId);
var message = $.extend({}, defaultMessage);
message.id = fromUserId + '_' + Math.floor(Date.now() / 1000);
message.from = sender.username;
message.fromUserId = fromUserId;
message.to = receiver.username
message.toUserId = toUserId;
message.message = msg;
message.date = new Date();
sender.messages.outbox.push(message);
receiver.messages.inbox.push(message);
}
/* TODO: delete, move etc. */
}
userManagement.register('barry', 'barry#test.nl', 'bcf2ibc');
userManagement.register('john', 'john#test.nl', 'bahjscb');
userManagement.login('test', 'blabla'); // fail
userManagement.login('barry', 'blabla'); // fail
userManagement.login('barry', 'bcf2ibc'); // success
userManagement.login('John', 'bahjscb'); // success
//userManagement.forgotPass('barry');
var barry = userManagement.getUserByUsername('barry');
var john = userManagement.getUserByUsername('John');
message.send(barry.userId, john.userId, 'My test message.');
message.send(barry.userId, john.userId, 'You received my previous message?');
message.send(john.userId, barry.userId, 'Yes I did received them.');
console.log(users);
JS Fiddle: https://jsfiddle.net/vmjs1n9n/12/
They way I setup the private message per user, is that a good thing to do? I would appreciate advice on the rest as well!

It's a start, if your primary intent is to facilitate private messages, then yes, private message per user is a good thing to do.
My first thoughts, you know you are re-inventing the wheel right? If I was given this as a business requirement I would integrate with an existing messaging service or protocol rather than have to deal with the long term management of this kind of data. Even authentication, in this day you should be attempting to implement some kind of open authentication standard, like OAuth, again to reduce the amount effort you need to spend to get this off the ground and keep it running long term.
I normally wouldn't put message data physically into the sender's outbox and then into the receivers inbox as well, primarily because your data storage would be double, but I guess like email, routing copies of the original message would make management of the messages really simple, whilst making it hard to accidentally give one user access to another's messages.
Here because you are prototyping, it's hard to provide decent comments because you have already alluded to the fact that you will do things differently in the backend so I don't want to second guess where you have already decided to go with this. For a simple system like this the UI should be really lite, with the logic in the backend, the specific logic is where I would like to provide future comments and insights.

Related

React Native App hanging while appending to array/Flatlist

So I have a app where I loades messages from my Server/Database. Now I have a big problem which is not really great for the users:
--> When I for loop the messages payload from the backend my whole App is hanging and I can't click anywhere else to e.g. go back and so on.
This is my for loop:
const handleMessagesPayload = (messages, new_page_number) => {
if (messages != null && messages != "undefined" && messages != "None"){
setPageNumber(new_page_number)
console.log(messages)
for (var i = 0; i < messages.length; i++) {
appendChatMessage(messages[i], false)
};
}
}
appendChatMessage function:
const appendChatMessage = (data, isNewMessage) => {
var msg = data.message
var timestamp = data.natural_timestamp
var user_id = data.user_id
var username = data.username
var message_id = data.message_id
logData(msg, timestamp, user_id, username, isNewMessage, message_id)
}
//add the new Messages to array
const logData = (msg, timestamp, user_id, message_username, isNewMessage, message_id) => {
const newMessage = {"message": msg, "username": message_username, "timestamp": timestamp, "message_id": message_id}
newChatMessage.push(newMessage) //newChatMessage is the array I was talking about
};
Do you have any useStates()? This might be the problem if you have any of them because they are very slow.

managing sessions on login nodejs

I am trying to manage user sessions in nodejs. I have built a dashboard where people will be able to manage their products for inventory and such. I basically have it running right now where a user logs in, and it stores there username in a global variable, and then userAuth gets set to true. Obviously in a prod env this would not work, so I am trying to manage each session. the user should log on, and they should have their own session, and all their database creds should be pulled from my master table, and then used for that specific session. multiple users should be able to use this and edit their products and inventory at the same time. I have tried express-session, but no luck, I'm doing something wrong but not sure where to start really. here's my login code:
//LOGIN FUNCTIONALITY
app.post("/login", (req, res) => {
//defining variables for users username & password inputs
const inputUsername = req.body.inputUsername;
const inputPassword = req.body.inputPassword;
//functionality to query db by username
var userLogin = "select * from login where USERNAME = ?";
ibmdb.open(ibmdbconnMaster, function (err, conn) {
if (err) return console.log(err);
conn.query(userLogin, [inputUsername], function (err, rows) {
if (err) {
console.log(err);
}
//if the query returns results that are > 0
if (rows.length > 0) {
var pass = "";
userSessionId = req.body.sessionID
var sessUsername = userUsername
//loop for getting those values that correspond with the username of the user
for (var i = 0; i < rows.length; i++) {
userUsername = rows[i]["USERNAME"];
pass = rows[i]["PASSWORD"];
firstName = rows[i]["FN"];
lastName = rows[i]["LN"];
company = rows[i]["COMPANY"];
ibmdbconnDash = rows[i]["DBCONNSTRINGDASH"];
ibmdbconnBlog = rows[i]["DBCONNSTRINGBLOG"];
mailerStatus = rows[i]["MAILERSTATUS"];
//these will be more secure when time comes
cloudinaryName = rows[i]["CLOUDINARYNAME"];
cloudinaryKey = rows[i]["CLOUDINARYKEY"];
cloudinarySecret = rows[i]["CLOUDINARYSECRET"];
}
//comparing user input password to hashed db password
bcrypt.compare(inputPassword, pass, function (err, result) {
console.log("result is " + result);
//if the result of the compare is true, then redirect to the index function
if (result == true) {
console.log("login works");
userAuth = "true"
res.redirect("/index");
} else {
//if compare returns false, re-render login page
userAuth = "false";
res.render("login.ejs");
alert("Incorrect username or password. Please try again");
}
});
//if the entire query returns rows < 1 (username and password don't match, then re-render login page)
} else {
userAuth = "false";
res.render("login.ejs");
alert("Incorrect username or password. Please try again");
}
conn.close(function () {
console.log("closed the function /login");
});
});
});
});
global variables
var userAuth = ""
var userName = "";
var firstName = "";
var lastName = "";
var company = "";
var password = "";
var ibmdbconnMaster =
"db2 conn string";
var ibmdbconnDash = "";
var ibmdbconnBlog = "";
var userUsername = "";
var mailerStatus = "";
var cloudinaryName = "";
var cloudinaryKey = "";
var cloudinarySecret = "";
I have tried implementing sessions using express-sessions, the code I had set up for that was the standard code from their site:
app.use(session({
secret: "sec",
resave: false,
uninitialized: true,
}))
main index / landing page (dashboard) function
//DEFINING GLOBAL VARIABLES FOR AUTH
var sessionID = "";
var numOfOrders = "";
var numOfUsersM = "";
var userAuth = ""
var userName = "";
var firstName = "";
var lastName = "";
var company = "";
var password = "";
var ibmdbconnMaster =
"db conn string";
var ibmdbconnDash = "";
var ibmdbconnBlog = "";
var userUsername = "";
var mailerStatus = "";
var cloudinaryName = "";
var cloudinaryKey = "";
var cloudinarySecret = "";
//manage sessions
app.use(session({
secret: 'secret-key',
resave: true,
saveUninitialized: true,
}))
//rendering login page
app.get("/login", (req, res) => {
res.render("login.ejs");
});
/
//LOGIN FUNCTIONALITY
app.post("/login", (req, res) => {
// console.log("sessionsid is: " + req.body.sessionID)
// sessionID = req.body.sessionID
//defining variables for users username & password inputs
const inputUsername = req.body.inputUsername;
const inputPassword = req.body.inputPassword;
//functionality to query db by username
var userLogin = "select * from login where USERNAME = ?";
ibmdb.open(ibmdbconnMaster, function (err, conn) {
if (err) return console.log(err);
conn.query(userLogin, [inputUsername], function (err, rows) {
if (err) {
console.log(err);
}
//if the query returns results that are > 0
if (rows.length > 0) {
var pass = "";
//var userUsername = ""
userSessionId = req.body.sessionID
var sessUsername = userUsername
//loop for getting those values that correspond with the username of the user
for (var i = 0; i < rows.length; i++) {
var userUsername1 = rows[i]["USERNAME"];
pass = rows[i]["PASSWORD"];
firstName = rows[i]["FN"];
lastName = rows[i]["LN"];
company = rows[i]["COMPANY"];
ibmdbconnDash = rows[i]["DBCONNSTRINGDASH"];
ibmdbconnBlog = rows[i]["DBCONNSTRINGBLOG"];
mailerStatus = rows[i]["MAILERSTATUS"];
cloudinaryName = rows[i]["CLOUDINARYNAME"];
cloudinaryKey = rows[i]["CLOUDINARYKEY"];
cloudinarySecret = rows[i]["CLOUDINARYSECRET"];
}
//comparing user input password to hashed db password
bcrypt.compare(inputPassword, pass, function (err, result) {
console.log("result is " + result);
//if the result of the compare is true, then redirect to the index function
if (result == true) {
console.log("login works");
var userAuth1 = "true"
//successful login
req.session.user = {
userUsername1,
userAuth1
}
console.log("rquu1 " + req.session.user.userUsername1)
res.redirect("/index");
} else {
//if compare returns false, re-render login page
userAuth1 = "false";
res.render("login.ejs");
alert("Incorrect username or password. Please try again");
}
});
//if the entire query returns rows < 1 (username and password don't match, then re-render login page)
} else {
userAuth = "false";
res.render("login.ejs");
alert("Incorrect username or password. Please try again");
}
conn.close(function () {
console.log("closed the function /login");
});
});
});
});
//function for logout page
app.get("/logout", (req, res) => {
userAuth = "false";
res.render("login.ejs");
});
//RENDERING INDEX PAGE WITH INFORMATION ABOUT PRODUCTS AND ANALYTICS
app.get("/index", (req, res) => {
// if (userAuth == "true") {
if (req.session.user) {
console.log(req.session.user)
console.log("username is: " + userName);
pageName = "/index";
numOfOrdersFun(req, res, numOfOrders)
//end of location manager
//initializing counter
var counterTest2 = "select * from VISITORS";
ibmdb.open(ibmdbconnDash, function (err, conn) {
if (err) return console.log(err);
conn.query(counterTest2, function (err, rows) {
if (err) {
console.log(err);
}
for (var i = 0; i < rows.length; i++) {
var dbCountCurrent = rows[i]["NUM"];
}
console.log("currentCount " + dbCountCurrent);
conn.close(function () {
console.log("closed the function /login");
});
//showing information for products
var showingDBINFO = "SELECT * FROM PRODUCTS";
ibmdb.open(ibmdbconnDash, function (err, conn) {
if (err) return console.log(err);
conn.query(showingDBINFO, function (err, rows) {
if (err) {
console.log(err);
}
//rendering page with all users information, products, and data from login. also a redirect from the login info.
res.render("index", {
page_title: "index",
data: rows,
userName: userName,
FN: firstName,
LN: lastName,
CO: company,
dbcc: dbCountCurrent,
numOfOrders: numOfOrders,
mailerStatus: mailerStatus,
});
conn.close(function () {
console.log("closed the function /index);
});
});
});
});
});
} else {
req.session.user.userAuth1 == "false"
res.render("login.ejs");
}
});
but now im confused on how to manage each session individually when their are so many global variables I have that are needed for each session, and would users be able to use the app simultaneously?
thanks for the help!
When using express-session you can use the req.session object and store your preferred data. In your concrete example you could set all the information about the user you need later in your code to req.session.user.
Tiny example:
//successful login
req.session.user = {
userName,
firstName
}
If you need to access any information about the user later, just use req.session.user.userName for instance.
This data is stored server-side and is also available in new requests.
Please also note that the secret shouldn't be the default, instead use a strong & generated password nobody knows.

How to make async callback in node and make sure HTML form data is available for saving to db

How can I make callback and variables so that I can save data to my database?
I have node app.post like below. I need to convert form data to mongoose model. The data what I'm getting is in two arrays and only data which has amount larger than 0 is searched and saved, but this don't work and I can't get around it.
I think that looping and searching for ingredients should be a function and Meal.save should be in callback but I don't know how. I've been banging my head into this problem for weeks and I have googled, but this just does not open to me. Please help me with this.
Thanks in advance!
app.js
app.post("/diary/:id/dayshow", function(req, res) {
// Get the day I want to save my meal data
Day.findById(req.params.id, function(err, day) {
if (err) {
console.log(err);
res.redirect("/diary");
} else {
// This is the format I have in the mongoose model
// and I need to convert HTML form data to this
var singleMeal =
{
// title: dinner
// ingredients: [
// {
// ingredient:{},
// amount: Number
// }
// ]
}
var singleMealTempArr = [];
var singleIngredientObj = {};
var amount;
singleMeal.title = req.body.title;
// Looping through the HTML form data and converting it to mongoose model
// I want to loop data and search mongo first and after that I need to save
// the data to mongo which happens in Meal.save()
for (var i = 0; i < req.body.amount.length; i++) {
var _id = req.body.id[i];
amount = Number(req.body.amount[i]);
if (amount !== 0) {
singleIngredientObj.amount = amount;
// Searching ingredient from database with ID what is from the HTML form
Ingredient.findById({_id}, function(err, foundIngredientData){
console.log(foundIngredientData + "<<<<<<<<<<<<< ingredientData");
singleIngredientObj.ingredient = foundIngredientData;
singleMealTempArr.push(singleIngredientObj);
console.log(JSON.stringify(singleMealTempArr) + "<<<<<<<<<<<< JSON.stringify(singleMealTempArr)");
});
}
}
singleMeal.ingredients = singleMealTempArr;
// Now I should have data in singleMeal variable, but it has only title and
// empty array of ingredients
console.log("JSON.stringify(singleMeal) >>>>>>>>>" + JSON.stringify(singleMeal) + "<<<<< JSON.stringify(singleMeal)");
}
Meal.create(singleMeal, function(err, singleMealObject) {
if (err) {
console.log(err);
} else {
console.log("--- You hit the Meal.create + Save -----" + "singleMealObject: " + singleMealObject);
// day.meals.push(singleMealObject); <-- These two are commented because previous steps dont work and singleMealObject has only title and empty array of ingredients
// day.save();
res.redirect("/diary/" + day._id + "/dayshow");
}
});
});
});
console.logs what I get from the above is here:
JSON.stringify(singleMeal) >>>>>>>>>{"title":"aa","ingredients":[]} <<<<< JSON.stringify(singleMeal)
{ _id: 597c11c04a7bce08cdcdef41,
name: 'oatmeal',
kcal: 100,
protein: 2,
carb: 50,
fat: 1,
addinfo: '',
__v: 0 } <<<<<<<<<<<<< ingredientData
[{"amount":3,"ingredient":{"_id":"597c11c04a7bce08cdcdef41","name":"oatmeal","kcal":100,"protein":2,"carb":50,"fat":1,"addinfo":"","__v":0}}] <<<<<<<<<<<< JSON.stringify(singleMealTempArr)
{ _id: 597c11c04a7bce08cdcdef41,
name: 'oatmeal',
kcal: 100,
protein: 2,
carb: 50,
fat: 1,
addinfo: '',
__v: 0 } <<<<<<<<<<<<< ingredientData
[{"amount":3,"ingredient":{"_id":"597c11c04a7bce08cdcdef41","name":"oatmeal","kcal":100,"protein":2,"carb":50,"fat":1,"addinfo":"","__v":0}},{"amount":3,"ingredient":{"_id":"597c11c04a7bce08cdcdef41","name":"oatmeal","kcal":100,"protein":2,"carb":50,"fat":1,"addinfo":"","__v":0}}]<<<<<<<<<<<< JSON.stringify(singleMealTempArr)
--- You hit the Meal.create + Save -----singleMealObject: { __v: 0,
title: 'aa',
_id: 597c11cb4a7bce08cdcdef61,
ingredients: [] }
You can check this stackoverflow answer for getting records respective to ids.
mongodb/mongoose findMany - find all documents with IDs listed in array
app.post("/diary/:id/dayshow", function(req, res) {
// Get the day I want to save my meal data
Day.findById(req.params.id, function(err, day) {
if (err) {
console.log(err);
res.redirect("/diary");
} else {
// This is the format I have in the mongoose model
// and I need to convert HTML form data to this
var singleMeal =
{
// title: dinner
// ingredients: [
// {
// ingredient:{},
// amount: Number
// }
// ]
}
var singleMealTempArr = [];
var amount;
singleMeal.title = req.body.title;
function generateMeal(callback) {
var meal_ids = [];
for (var i = 0; i < req.body.amount.length; i++) {
var singleIngredientObj = {};
var _id = req.body.id[i];
amount = Number(req.body.amount[i]);
if (amount !== 0) {
meal_ids.push(_id);
singleIngredientObj.amount = amount;
singleMealTempArr.push(singleIngredientObj);
}
}
Ingredient.find({_id : meal_ids}, function(err, getIngredientsOfIds){
// not added amount. you can do it data massage whatever you want
if(err) {
//error handling
return;
}
for(var i = 0; i < singleMealTempArr.length; i++) {
singleMealTempArr[i].ingredients = getIngredientsOfIds[i];
}
singleMeal.ingredients = singleMealTempArr;
callback();
});
}
function createMeal() {
Meal.create(singleMeal, function(err, singleMealObject) {
if (err) {
console.log(err);
} else {
console.log("--- You hit the Meal.create + Save -----" + "singleMealObject: " + singleMealObject);
// day.meals.push(singleMealObject); <-- These two are commented because previous steps dont work and singleMealObject has only title and empty array of ingredients
// day.save();
res.redirect("/diary/" + day._id + "/dayshow");
}
});
}
generateMeal(createMeal);
});
});

How to make a simple webpage register form using cookies? (jQuery)

I'm making a register/login form in javascript. User should enter information about himself and the computer should put that information into an array and remember it but it 'forgets' it every time I reload the page.
else {
document.cookie = email;
cookies[cookies.length] = document.cookie;
$('#error').text("Your registration is complete.");
break;
}
...more code
$('.btn').click(function() {
alert(cookies[cookies.length - 1]);
});
Any ideas to solve this? I have one more question. How can I check weather is an username alerady in use?
Here is the full js code:
var main = function() {
var people = [];
var cookies = [];
$('#register_email').val("");
$('#register_username').val("");
$('#register_password').val("");
$('#register2_password').val("");
function Person(username, email, password, repeat_password) {
this.username = username;
this.email = email;
this.password = password;
this.repeat_password = repeat_password;
}
$('#register').click(function() {
var username = $('#register_username').val();
var email = $('#register_email').val();
var password = $('#register_password').val();
var r_password = $('#register2_password').val();
if( email==="" || username==="" || password==="" || r_password==="") {
$('#error').text("You didn't fill everything");
}
else {
people[people.length] = new Person(username, email, password, r_password);
for(var key in people) {
//This should check weather this username was used before but I'm not really sure what to insert instead of "name"
if(people[people.length - 1].username === "name") {
$('#error').text("This username is already in use");
break;
}
else if(password !== r_password) {
$('#error').text("Passwords don't match");
break;
}
else {
document.cookie = email;
cookies[cookies.length] = document.cookie;
$('#error').text("Your registration is complete.");
break;
}
}
}
});
$('.btn').click(function() {
alert(cookies[cookies.length - 1]);
});
};
$(document).ready(main);
There is a js-fiddle live example in comments.

Node.js socket.io handling users

So at my server app when I get a socket request I send data based on what user is requesting the information...
server.on('connection', function(socket) {
socket.on('login', function(data) {
connection.query('SELECT * FROM users WHERE name = ? AND password = ? LIMIT 1', [data.name, data.password], function(err, result) {
if(result.length === 0)
{
socket.emit('login-failed');
}
else
{
if(users.check(result[0].name))
{
result[0].socket = socket.id;
users.add(result[0]);
console.log(colors.yellow('User: ' + result[0].name + ' connected.'));
socket.emit('login-success');
}
}
});
});
So when a user logs in I save some information like username, password, socketid.
var userList = [];
exports.add = function(data)
{
userList.push(data);
}
exports.check = function(data)
{
for(var i = 0; i < userList.length; i++)
{
if(userList[i].name === data)
{
return false;
}
}
return true;
}
exports.remove = function(id)
{
for(var i = 0; i < userList.length; i++)
{
if(userList[i].socket === id)
{
var index = userList.indexOf(i);
userList.splice(index, 1);
return true;
}
}
return false;
}
So as you can see Im saving users data that I will access later for example on here
socket.on('test', function(data) {
if(users.remove(socket.id)) console.log('Yes');
});
But the only way I have to identify a socket is by using its socket.id, now my question is if I can really trust socketid or if I should use another 'system' to actually manage my users logic.
I cant really figure any other system to actually check what socket is calling my server

Categories

Resources