Sqlite3, user already exists while it does not - node.js

app.post('/register', function(req,res){
console.log("register post got", req.body)
if (req.body.username && req.body.password) {
db.get("SELECT * FROM Users WHERE username = '" + req.body.username + "' LIMIT 1");
res.end("Account already exists");
var stmt = db.prepare("INSERT INTO user VALUES (?,?)");
stmt.run(req.body.username, req.body.password);
res.end("OK");
} else {
res.end("username and password are requesiraehri");
}
});
What's wrong here, because If I'm trying to register user, it says it already exists while the db is completely empty.
Any help?

In all that follows, I assume you are using this sqlite library: https://www.npmjs.com/package/sqlite3
res.send("Account already exists"); is called unconditionally. You forgot to check the result of your query.
But there are other issues in your code. Frist of all, you are not using async functions with callbacks. db.get is an asynchronous function and takes a callback as a second argument, which receives either the first row of the resultset or an error (see documentation).
app.post('/register', function(req,res){
console.log("got register post", req.body)
if (req.body.username && req.body.password) {
db.get("SELECT * FROM Users WHERE username = ? LIMIT 1", req.body.username, function(err, row){
if(row){
res.end("Account already exists");
} else {
var stmt = db.prepare("INSERT INTO user VALUES (?,?)");
stmt.run(req.body.username, req.body.password);
res.end("OK");
}
}
} else {
res.end("username and password are required");
}
});
stmt.run is also asynchronous. So be aware, that res.end('OK') is executed before the data is inserted into the database. It would be probably better to check if the insert statement is run successfully before sending the response.
Another important issue is that you insert the password in clear in the database. You should think about crypting it. Never store passwords in cleartext !

Related

How to fix error: Cannot set headers after they are sent?

I am using PostgreSQL for the first time with an express server and am running into an error. On my register user route I am trying to check if the username or email already exists, because they need to be unique. What keeps happening is, say I pass in a username that is already in the database then the first return will run and return that the username is already in use. But what is happening is it is returning the username is already in use and it still running the rest of the code so it trying to return multiple json responses.
module.exports.register = async (req, res, next) => {
try {
const { username, email, password } = req.body;
postgres
.query("SELECT * FROM users WHERE username = $1", [username])
.then((data) => {
if (data.rows.length > 0) {
return res.status(409).json({
msg: "Username is already in use",
status: false,
});
}
})
.catch((err) => {
console.log(err);
});
postgres
.query("SELECT * FROM users WHERE email = $1", [email])
.then((data) => {
if (data.rows.length > 0) {
return res.status(409).json({
msg: "Email is already in use",
status: false,
});
}
})
.catch((err) => {
console.log(err);
});
const hashedPassword = await bcrypt.hash(password, 10);
postgres.query(
"INSERT INTO users (username, email, password) VALUES ($1,$2,$3) RETURNING *",
[username, email, hashedPassword],
(err, data) => {
if (err) {
console.log(err.stack);
} else {
return res.json({ user: data.rows, status: true });
}
}
);
} catch (err) {
next(err);
}
};
I can't figure out why the rest of the code is running even though I am returning res.json. If anybody has any suggestions/solutions I would really appreciate it!
The return in front of the res.status(409) is returning you out of the then of the postgres.query function instead of the full register function. As a result it jumps out of the then and runs the rest of the code from there, so it's still hashing the password and attempting an insert into the users table (which hopefully fails on a unique index).
In order to fix this you can either 1) Define a variable before the function, change it if something was found and then do a return outside of the then statement if the variable was changed 2) perform all the rest of the code in the then statement (since you're returning out of that it will not be run) or 3) use awaits instead and throw/next+return/res.json+return an the HTTP 409 error.
Option 3 will take the most effort but you should definitely learn to use this route as soon as possible as it makes writing async code a lot easier (plus you'll avoid getting a bunch of nasty nested then statement). You could try out using option 1 and 2 just to get a feel for how the flow of the express code works.

Can't change the password of a user with User.update() in sailsjs, fetch returns [Deferred]

I'm using postgresql(Elephant SQL) and I hadnt had issues creating and finding users inside this database. And this is my method. It's pretty straight forward and most of it shouldn't even matter to the question. What I'm lacking is the ability to change a users password, or anything really. It finds the correct user and pretty much anything up to the point where it needs to change an entry works as expected.
updatePassword: async function(req,res){
if(req.body.password){
console.log("PUT BODY" + req.body.password);
var newPass = req.body.password;
var userId = req.session.userId;
var foundUser = await User.findOne({id:userId},function(err,user){
if(err){
return res.status(500).json({err:'database error'});
}
if(user){
var hashedPass = bcrypt.hashSync(newPass, bcrypt.genSaltSync(8), null);
console.log("Found user");
console.log(userId);
console.log(hashedPass);
var updateUser = User.update(user).set({password:hashedPass}).fetch();
console.log(updateUser);
if(updateUser){
return res.status(200).json({status:'success'});
}
else{
return res.status(500).json({err:'database error'});
}
}
if(!user){
return res.status(500).json({err:'database error'});
}
});
}
else{
return res.status(401).json({err:'empty body'});
}
},
I've been debugging this for quite some time and I can't figure it out at all. The user found is correct and I can get his current attributes, but I can in no way change their passwords.
Can anyone provide some insight? Maybe adding some stuff: this is a PUT request, only containing:
password:iaj34x
I can also parse the request alright. All I'm missing is the update command executing properly. The value of
updateUser
is
[Deferred]
And I have no idea how to get any more info on this.
Using this as an example(from the docs):
await User.update({name:'Pen'})
.set({name:'Finn'});
I'm doing the syntax correctly.
Was missing an await next to the function. "Works" now, even though I have issues with re-logins, it changes the password in the database.
var updateUser = await User.update(user).set({password:hashedPass}).fetch();

What's the correct syntax to check if cypher query return zero row in javascript

I am trying to determine if a username exists before creating the user. I am using the following code. I need an elegant way to determine if the zero row is returned ...username doesn't exist. for example I know the returned row value would be zero if not found. How can I get access to the row value in the code. Can someone assist...thanks...BTW I am using neo4j3.0 Nodejs with express and Passport
neo4jSession
.run(MATCH (user {email: newUser.email}) RETURN user);
.then (function(result) {
if ((not found) {
.run(CREATE (user: {email:newUser.email, password:newUser.password} ) ASSERT email is UNIQUE RETURN user);
neo4jSession.close();
}) //end of if not found
else (found)
{
// email address already exist
console.log("email address already exist");
neo4jSession.close();
}
}); //end .then
.catch(function(error) {
console.log(error);
});
The Neo4j Driver for JavaScript record module can check if a value from record exists by index or field key using the has method. When evaluating or validating the existence of any field within a record (e.g. determining if a User node contains an existing email address property), using the has instead of the get method can allow for shorter Cypher statements and condensed javascript code; which (IMO) can lead to elegance you are seeking.
Using your original example, you can use a simple Cypher statement to search if a User node contains an email property by passing in a user's input. Utilizing the Neo4j Driver for JavaScript, you can return a result stream with a single record.
Cypher Statement:
MATCH ( u:User { email: $email } )
RETURN u, u.email
If an email address exists as a User node property in the Neo4j database, a stream of records with one field named "u.email" be will returned . The record represents one user found by the statement above. You can access the field value by key using the record module's has method.
Access Record by Field Key:
result.records[0].has('u.email')
The following example is one of many ways you could implement both the simple Cypher statement and has method:
async (_, { email, password }) => {
const session = await driver.session()
const closeSession = await session.close()
const endSession = await driver.close()
let query = 'MATCH (u:User{email: $email}) RETURN u, u.email'
return session
.run(query, { email })
.then(async result => {
closeSession()
let emailExists = result.records[0].has('u.email')
let newUser = result.records[0].get('u').properties
if (
(Array.isArray(result.records) && !result.records.length) ||
(Object.keys(result).length === 0 && result.constructor === Object)
) {
if (!emailExists) {
let query =
'MERGE (u:User { email: $email }) ON CREATE SET u.password = $password RETURN u'
return session
.run(query, { email, password })
.then(result => {
closeSession()
return newUser
})
} else if (Array.isArray(result.records) && result.records.length) {
const emailExists = result.records[0].has('u.email')
if (emailExists) {
closeSession()
throw new Error(emailExists + ' already exists.')
} else {
closeSession()
endSession()
throw new Error('Internal Server Error')
}
} else {
closeSession()
endSession()
throw new Error('Internal Server Error')
}
} else {
closeSession()
endSession()
throw new Error('Internal Server Error')
}
})
.catch(function(err) {
closeSession()
endSession()
if (err) throw err
})
}
Note: This example validates whether a record exists first by evaluating the result with conditional statements, then the e-mail property is checked. A few errors have been handled as well.
Query (use counter):
MATCH (user {email: newUser.email})
RETURN count(user)=1 as user_exists
In javascript:
if ( result.records[0].get('user_exists') !== true ) {
// create new user
}
And, of course, add a unique constraint to the email address for the user.
Though the answer from #stdob is an accepted answer on further research I found out that in case the record do exist, you can't retrieve any data on that query... so:
MATCH (user {email: newUser.email})
RETURN user.name AS Name, count(user)=1 as user_exists
wont yield any data if user exist. The following works:
MATCH (user {email: newUser.email}) RETURN user;
if (!result[0]) {
//no records found
}
else {get user properties}
Thanks to:
https://github.com/mfong/node-neo4j-passport-template/blob/master/models/user.js

mongoose findOne() query called last in function

New to Node and Mongoose here. I am having trouble running my mongoose findOne() query in a synchronous fashion within a function. Here is my code:
exports.read = function(req, res){
console.log("in articles controller read()");
//try to get article creatorId and use user providerData
//name to make fullName
var userName = "";
//get article creator id
User.findOne({ '_id': req.article.creator._id }, function(err, person){
if(err) { return next(err)};
if (!person) { return next(new Error('Failed to find user'))};
console.log("found person");
//return providerData name
userName = person.providerData.name;
});
//assign username value to article creator
var splitName = userName.split(' ');
req.article.creator.fullName = userName;
req.article.creator.firstName = splitName[0] || '';
req.article.creator.lastName = splitName[1] || '';
console.log("end of read()";
res.json(req.article);
};
When I look at my console, I expect to see the logs in the following order:
in articles controller read()
found person
end of read()
But instead, I see in my console:
in articles controller read()
end of read()
found person
I'm assuming that this issue has to probably do with the async nature of node?
Basically, I would like to run the findOne() query before assigning values to my req object so that I can actually have something to assign. Please help.
Callbacks are async, you need to move your code inside it.
User.findOne({ '_id': req.article.creator._id }, function(err, person){
if(err) { return next(err)};
if (!person) { return next(new Error('Failed to find user'))};
console.log("found person");
//return providerData name
userName = person.providerData.name;
//assign username value to article creator
var splitName = userName.split(' ');
req.article.creator.fullName = userName;
req.article.creator.firstName = splitName[0] || '';
req.article.creator.lastName = splitName[1] || '';
res.json(req.article);
});
You are using the Nodejs which is asynchronous and event-driven.
So it will call the method in sequence way:
console.log("in articles controller read()");
User.findOne();
console.log("end of read()";
but User.findOne is the database call which is slow, so it call User.findOne and it will go tho then another method call and when they will return the result it will print.
That's by you will get the result as
in articles controller read()
end of read()
found person
For solving this you can use the async.js or you can directly put the value inside the findOne result:
exports.read = function(req, res){
console.log("in articles controller read()");
//try to get article creatorId and use user providerData
//name to make fullName
var userName = "";
//get article creator id
User.findOne({ '_id': req.article.creator._id }, function(err, person){
if(err) { return next(err)};
if (!person) { return next(new Error('Failed to find user'))};
console.log("found person");
//return providerData name
userName = person.providerData.name;
//assign username value to article creator
var splitName = userName.split(' ');
req.article.creator.fullName = userName;
req.article.creator.firstName = splitName[0] || '';
req.article.creator.lastName = splitName[1] || '';
console.log("end of read()");
res.json(req.article);
});
}

Error "Undefined is not a function " Using callback node.JS

I am trying to save a new Document (user) in my MongoDb and I use callback. The code runs and goes until save the user, but after that I get an error.So I can save user. I have the following code:
function saveUser(userName, socialMediaType, socialMediaID, setDocNumber, callback){
var user;
if(socialMediaType == "fbUID"){
user = new users({
userName: userName,
userEmail: 'userEmail',
teams:[],
fbUID : socialMediaID
});
}else
if(socialMediaType =="google"){
//do the same
}
var query = {}
query["'"+ socialMediaType +"'" ] = socialMediaID
users.findOne(query, function(err, userFound){
if (err) { // err in query
log.d("Error in query FoundUser", err)
log.d("User Found", userFound)
}else
if(userFound == undefined){ //if user does not exist
user.save(function(err, user){
if(err) return console.error(err);
log.d("user saved", user);
currentSession = sessionOBJ.login(user._id, socialMediaID);
callback(currentSession,"created")
});
}else{
currentSession = sessionOBJ.login(userFound._id, socialMediaID);
callback(currentSession,"logged")
}
});
}
I call the function above through this code:
f(fbUID !== undefined){
userModelOBJ.saveUser(userName,"fbUID", fbUID, function(currentSession, status) {
res.send({"status":status,
"sessionID": currentSession.sessionID,
"expires" : currentSession.date});
});
I am getting this error :
The error is in the line :
callback(currentSession,"created")
What could be the problem?
I already did many researchers but this is a specific case.
Your saveUser() call is missing the setDocNumber argument. It looks like you're not using it in your code though, so you might be able to safely remove it. If you are using it somewhere else (that you haven't shown) then you need to do some argument checking at the top of saveUser() to support optional arguments.

Resources