I am currently involved helping out on a project which involves using the Geddy js framework, which it is my first time using. I am currently trying to fix the create method inside a model for users. Here is the code below:
this.create = function (req, resp, params) {
var self = this
, user = geddy.model.User.create(params);
//need to ensure that the user agrees with the terms and conditions.
// Non-blocking uniqueness checks are hard
geddy.model.User.first({username: user.username}, function(err, data) {
if (data) {
params.errors = {
username: 'This username is already in use.'
};
//self.transfer('add');
}
else {
if (user.isValid()) {
user.password = cryptPass(user.password);
user.suburb = "";
user.state = "";
user.postcode = "";
}
user.save(function(err, data) {
if (err) {
params.errors = err;
self.transfer('add');
}
else {
// setup e-mail data with unicode symbols
var mailOptions = {
from: "App ✔ <hello#app.com>", // sender address
to: user.email, // list of receivers
subject: user.username + " Thank you for Signing Up ✔", // Subject line
text: "Please log in and start shopping! ✔", // plaintext body
html: "<b>Please log in and start shopping!✔</b>" // html body
}
smtpTransport.sendMail(mailOptions, function(error, response){
if(error){
console.log(error);
}else{
console.log("Message sent: " + response.message);
}
// if you don't want to use this transport object anymore, uncomment following line
smtpTransport.close(); // shut down the connection pool, no more messages
});
self.redirect({controller: self.name});
}
});
}
});
};
If you look in the code there is apparently a check to see if the so-called user is valid like so: if (user.isValid()) {
user.password = cryptPass(user.password);
user.suburb = "";
user.state = "";
user.postcode = "";
}
The proceeds on to 'save' regardless whether or not the user is valid. I'm thinking why is the code this way? It sounds nonsensical. I asked the original developer who was on the project about it and he said the model was apparently generated when he created the project.
So in bit of a confused state, if anyone can tell me why the save method is outside the if statement in the first place? Is it something the original creators of Geddy intended? or is really nonsensical and I should change it?
Thanks.
Geddy's save() call will error out if the data is invalid (unless force flag is set, which it isn't). It uses the same isValid() call actually. So, looks like what you have here is just someone's way to have a single error handler for all the error cases.
For user.password being set with crypted data only if the data looks valid, I'm guessing this is simply to make 'must be set' type of validation to work. Chances are that even with an empty password, the crypted string would be otherwise counted as set.
Related
So I'm trying to Create a reset page using restful API. I haven't found much info on the internet and I'm probably no using the best method. What I'm trying to do is send a code in the email of the user and then after the user typing the code will be decided if he can or cannot update the pass. I can't seem to find a way to pass the value of the code generated on the first request to the second to check if its correct. Any help is appreciated. Thanks in advance!
//ForgotPassword?
app.get('/forgotpassword/:username', function (_req, res) {
var seq = (Math.floor(Math.random() * 10000) + 10000).toString().substring(1);
console.log(seq);
mysqlConnection.connect(function () {
mysqlConnection.query('SELECT Email from Customer Where Username = ?', [_req.params.username], (err, results, _fields) => {
if (!err){
console.log(results[0].Email);
var mailOptions = {
from: 'myemail',
to: results[0].Email,
subject: "Password Reset Verification",
text: "If you did not request this, please ignore this email and your password will remain unchanged. CODE: " + seq,
};
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
console.log(error);
//Handle error here
res.send('Please try again!');
} else {
console.log('Email sent: ' + info.response);
res.send('Sent!');
}
})
}
else
console.log(err);
})
})
});
//CodeRandomCodeFromResetPass
app.get('/reset', function (req, res) {
var code;
//if code typed is = to seq sent in the email
res.send("The code is correct");
});```
//then I'll create a post request that updates the password username from the first get request
The code sent in email should be store in a table or collection. So code will be store against the email and an expiry time of the code. So in the next phase when the code will pass with an email you can check that this(entered) email should belong to this(entered) code within this(expiry time of code) time frame, so if condition satisfied then requested user can reset/change the password.
I am trying to update the user account details in firebase but I have noticed that the input value for one of my fields keeps coming up as undefined even when I console.log it. I am working in two files one is a loginjs file in which I am defining the user input.
signUpForm.addEventListener('click', function (e) {
e.preventDefault();
isSigningUp = true;
var email = signUpEmailInput.value;
var password = signUpPasswordInput.value;
var displayNameUser = displayNameInput.value;
var userPrivateKey = signUpPrivateKey.value;
var user = firebase.auth().currentUser;
var photoURL = "https://www.gravatar.com/avatar/" + md5(email);
if (signUpPasswordInput.value !== signUpPasswordConfirmInput.value) {
setSignUpError('Passwords do not match!');
} else if (!displayNameUser) {
setSignUpError("Display Name is required!");
} else if (!userPrivateKey) {
setSignUpError('You need to set a Private Key!');
} else {
auth.createUserWithEmailAndPassword(email, password)
.then(function (user) {
user.updateProfile({
displayName: displayNameUser,
photoURL: photoURL,
privateKey: userPrivateKey
}).then(function () {
// Update successful.
window.location.href = 'chat.html';
}).catch(function (error) {
// An error happened.
window.alert("Some unexpected error happened!");
});
user.sendEmailVerification().then(function () {
// Email sent.
}).catch(function (error) {
// An error happened.
window.alert("Email was not able to send!");
});
})
.catch(function (error) {
// Display error messages
setSignUpError(error.message);
});
}});
The weird thing is that the user input for my displayname and photoURL are working just fine, but when it comes to my private key user input it registers the input when it goes to the chat page and I do a console.log(user.privatekey) It says it is undefined.
In my chatjs file, thats when I am pushing the all the user profile information. The chatjs file basically allows a user to send a message, the message and all the user profile information gets stored onto the firebase database.
messages.push({
displayName: displayName,
userId: userId,
pic: userPic,
text: myString.toString(),
privatekey: user.privatekey,
timestamp: new Date().getTime() // unix timestamp in milliseconds
})
.then(function () {
messageStuff.value = "";
})
.catch(function (error) {
windows.alert("Your message was not sent!");
messageStuff;
});
The thing again is that the privatekey does not get stored at all, which is what I am not understanding, since it is registering user input in the loginjs file but when I go to the chatjs file it keeps saying the value is undefiend. I have googled everywhere and I still haven't found a solution to it. Any help would be greatly appricated!
It's because the Firebase user object you receive from Firebase is not customizable. When you call the createUserWithEmailAndPassword(email, password) method, it returns a specifically defined user object back to you - check out the docs for the properties of this object.
The properties displayName and photoURL both work because they are already properties of the user returned. privateKey is not an existing property of the Firebase user object, and Firebase doesn't know how to handle an update call for a property that isn't defined. Check out this question & answer where Frank explains that Users in Firebase aren't customizable - you need to store any extra info separately.
I am trying to build a basic Auth using post
app.post("/api/auth",function(req,resp)
{
var username = req.body.username||req.param('username');
var password = req.body.password||req.param('password');
log("Performing Log Check");
log(username + " "+password);
var sent ={};
sent.status =false;
sent.authenticated = false;
var query = {}
query.sql= "SELECT * FROM voix_auth";
query.timeout= 4000; // 40s
connection.query(query, function (error, rows, fields)
{
if(!error)
{
var i=0;
while(i!=rows.length)
{
if(rows[i].username == username && rows[i].password == password)
{
log(rows);
sent.status = true;
sent.authenticated = true;
sent.token = tokenData;
log(sent);
break;
}
i+=1;
}
resp.send(sent);
} //Error Ends
else
{
log("Error Occured");
}
}); //connection Query
log(sent);
resp.send(sent);
});
The issue here is that I get Cannot set header After They are Sent.
So when I remove resp.send() this error is gone.
But if the response I get is always false even though the user is Authenticated.
Please help.
You cant send out multiple responses.
Things to change
Change query to something like select ONLY_STUFF_YOU_NEED from table where username & passwords match. Take care of sql injection.
Wrap the query in a function that returns back a valid user object ONLY if auth matches. Move it outside the controller. Example + shameless plug - https://github.com/swarajgiri/express-bootstrap/tree/master/core
After auth is done, send the response using res.send
I have a checkbox input in my html which the user can check if he/she wishes to stay logged into the app after the browser has been closed. I would like to change between remember: "default", and remember: "sessionOnly" depending on whether the user checks the box or not.
This is my function to check whether the box in the html is checked or not:
function checkLoginTerm() {
var result;
if(document.getElementById('#loginkeeping').checked) {
result = "sessionOnly";
} else {
result = "default";
}
return result;
}
Then I call the function in my login function to be executed after the user authenticates like this:
function loginUser(username, password) {
if (checkVariable(username)) {var username = document.getElementById("loginUsername").value;}
if (checkVariable(password)) {var password = document.getElementById("loginPassword").value;}
firebaseRef.authWithPassword({
email : username,
password : password
}, function(error, authData) {
if (error) {
alert("Login Failed! "+ error, error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
}, {
remember: checkLoginTerm()
});
}
If I do this, the login process will never complete. But if I put the appropriate string directly after remember: (for example remember: "sessionOnly"), it will do what its told.
As pointed out by Rob DiMarco in the comments below my question, there were two minor issues -
The id of the element is loginkeeping and not #loginkeeping
I had made a logic error in the conditional statement within my checkLoginTerm() function
I'm performing server-side validation in the "Accounts.onCreateUser" function so that I can pass the options object as well. I wasn't able to figure out how to do this with the validate user function.
First, I'm totally open for correct if I'm going the wrong direction so please advise.
I can't figure out how to validate password length server-side. Is it because it's already converted prior to the creation? When testing, if I enter in a single character for password it doesn't throw an error.
Accounts.onCreateUser(function (options, user) {
if (options.profile) {
user.profile = options.profile;
user.profile.user_status = "new user";
}
// Error checking
var errors = "";
if (user.username.length === 0) {
errors = errors + '<li>Email is required</li>';
}
if (user.username.length !== 0 && user.username.length < 4) {
errors = errors + '<li>Email too short</li>';
}
if (user.profile.firstname.length === 0) {
errors = errors + '<li>First name is required</li>';
}
if (user.profile.firstname.length !== 0 && user.profile.firstname.length < 2) {
errors = errors + '<li>First name is too short</li>';
}
if (user.profile.lastname.length === 0) {
errors = errors + '<li>Last name is required</li>';
}
if (user.profile.lastname.length !== 0 && user.profile.lastname.length < 2) {
errors = errors + '<li>Last name is too short</li>';
}
if (user.services.password.length === 0) {
errors = errors + '<li>Please enter a password</li>';
}
if (user.services.password.length < 7) {
errors = errors + '<li>Password requires 7 or more characters</li>';
}
if (errors) {
throw new Meteor.Error(403, errors);
} else {
return user;
}
});
I'm not using Accounts-ui. Trying to roll out my own... Being completely new with Meteor it has been a bit of a battle trying to understand account creation and verification. If there's a way to do this with ValidateNewUser function should I be using that instead?
Thank you for all your help.
I've figured out the best manner to perform this. Hope this will help others.
I'm using a method on server side to validate and returning error if there is one. Then proceeding with the Account Creation.
Meteor.call('Validate_Registration', email, password, cpassword, firstname, lastname, terms, function(error) {
if (error) {
error = error.reason;
$('#Error-Block').fadeIn().children('ul').html(error);
console.log(error);
} else {
Accounts.createUser({
username: email,
email: email,
password: password,
profile: {
firstname: firstname,
lastname: lastname
}
}, function(error) {
if (error) {
error = error.reason;
$('#Error-Block').fadeIn().children('ul').html(error);
} else {
var uid = Accounts.connection.userId();
Meteor.call('Verify_Email', uid, email);
Router.go('/email-instructions');
}
});
}
});
The only thing I'm unsure of at this point is if it's correct to use:
var uid = Accounts.connection.userId();
This seems to be local to the current user only, and is stored in local storage to the user.
Accounts-password uses SRP, which is a bit complicated so I won't describe it fully here. The actual check of the hashed tokens happens around here Basically, the password does not arrive at the server as a plain text string therefore you will not be able to enforce password policy on the server, while using SRP.
Also notably around here there is a DDP only "plaintext" login option for those who (understandably) don't want to implement SRP on their own. As advertised, it should only be used if the user is connected w/ SSL. I would probably start there.
In the meantime, you can at least do some client side enforcing until you can roll your server-side login handler.
You may also want to check out this meteorhacks article for a custom login handler tutorial.
According to the documentation, the password "is not sent in plain text over the wire", so the password string you're looking at on the server side is not the same as what the user typed in.
EDIT: At least, that's what I think.
EDIT2: Found a comment in another question that confirms it.