Accounts.sendVerificationEmail Issue in Meteor - javascript

I Need to send VerificationEmail using Meteor.I did the code but It didn't send VerificationEmail and also got error on server side.Error is : Can't find user.I didn't have any idea about this.so Please see the below code & suggest me how to do.
JS Code:
if (Meteor.isClient)
{
Template.main.events
({
'submit #register-form' : function (e,t)
{
console.log("You pressed the button Register ");
e.preventDefault();
var username = t.find('#username').value
, name = t.find('#name').value
, email = t.find('#email1').value
, password = t.find('#pwd1').value;
console.log("password="+password);
var isValidPassword = function(val, field)
{
if (val.length >= 6) {
return true;
} else {
Session.set('displayMessage', 'Error & Too short.')
return false;
}
}
if (isValidPassword(password))
{
console.log(" *** isValidPassword *** ");
Accounts.createUser({email: email, password : password,username : username }, function(err)
{
if (err)
{
console.log(err);
}
else
{
console.log("Register Successfully");
Meteor.call('sendEmail',
'*****#gmail.com',
'****.com',
'Hello from Meteor!',
'This is a test of Email.send.');
}
});
}
else
{
console.log("*** Error ***");
}
}
});
}
if (Meteor.isServer)
{
Meteor.startup(function ()
{
// code to run on server at startup
});
//Meteor methods
Meteor.methods
({
sendEmail: function (to, from, subject, text)
{
Accounts.config({sendVerificationEmail: true, forbidClientAccountCreation: false});
process.env.MAIL_URL = 'smtp://****#gmail.com:*pwd*#smtp.gmail.com:587';
this.unblock();
Accounts.sendVerificationEmail(to);
}
});
}

Did you send the email to an email address? When you use to in Accounts.sendVerificationEmail(to);
it must be the _id of the user you want to send the confirmation email to, not their email address.

Related

Trouble solving: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

I'm working on a simple web app using node-pg and express.js with a login page and a dashboard that displays some data from a database.
The dashboard and all it's data loads fine initially using the following function after the user inputs their username and password:
const queryLogin = (request, response) => {
var username = request.body.username;
var password = request.body.password;
if (username && password) {
Promise.all([
pool.query('SELECT * FROM jobdesc WHERE complete=0 AND customer=$1 ORDER BY date_rec ASC LIMIT 10', ['somecustomer']),
pool.query('SELECT * FROM accounts WHERE email=$1 AND password=$2', [username, password],)
]).then(function([orderResults, results]) {
if (results.rows.length > 0) {
request.session.loggedin = true;
request.session.username = username;
var user = username;
var orderObj = orderResults.rows;
if (results.rows[0].account_type == 1) {
request.session.account_type = 1;
response.render('pages/index');
} else if (results.rows[0].account_type == 0) {
request.session.account_type = 0;
response.render('pages/dashboard', {
user: user,
orderObj: orderObj
});
} else {
console.log("Invalid Account Type");
}
} else {
response.send('Incorrect Username and/or Password!');
}
response.end();
}, function(error) {
throw error;
});
} else {
response.send('Please enter Username and Password!');
response.end();
}
}
The issue is that I have a link in my navbar that redirects to the dashboard (in the case that the user navigates to a different page and wants to return to the home page). When pressed I get the following error: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
The route I use to try and redirect to the home page is: app.get('/home', con.launchDashboard)
And the code for the function is:
const launchDashboard = (request, response) => {
if (request.session.loggedin) {
Promise.all([
pool.query('SELECT * FROM jobdesc WHERE complete=0 AND customer=$1 ORDER BY date_rec ASC LIMIT 10', ['somecustomer'])
]).then(function([orderResults]) {
if (request.session.account_type == 1) {
return response.render('pages/index');
}
else if (request.session.account_type == 0) {
var user = request.session.username;
var orderObj = orderResults.rows;
return response.render('pages/dashboard', {
orderObj: orderObj,
user: user
});
}
})
} else {
response.render('pages/login');
}
response.end();
}
I'm unsure of why I am getting this error, I am confused with where I am setting headers after they are sent to the client.

JQuery Custom Validation Rule Mysql function always showing error

I am trying to add a custom validation rule to check if username exists or not. My code:
jQuery.validator.addMethod("checkexist", function(myvalue, element) {
checkifexist(function(result) {
if (result == true)
{
return true;
}
else
{
return false;
}
});
}, 'Does not exists!');
and
async function checkifexist(callback) {
const secret = keytar.getPassword('Userdata', 'MysqlPassword');
secret.then((result) => {
var mysql = require("mysql");
var connection = mysql.createConnection({
host: store.get('ip'),
port: store.get('port'),
user: store.get('username'),
password: result,
database: "database"
});
var querystring = 'SELECT * FROM `testdb`';
try
{
connection.query(querystring, (err, rows, fields) => {
if(err){
return callback("error with query", err);
}
var found;
for (var i in rows)
{
if (some check...)
{
return callback(true);
}
}
return callback(false);
});
connection.end(() => {
});
}
catch { }
});
However, if I check the valditation it correctly outputs true or false on every keypress. I still get only validation errors, though it should be a valid input.

How to fix "Error: Can't set headers after they are sent" in Express

I have recently been developing a MERN application and I have recently came into the trouble that express is saying that I am setting headers after they are sent.
I am using mongo db and trying to update a user profile.
I have tried to comment out my res.send points to find the issue but I have failed to do so.
Here is my post method for updating the user profile:
app.post("/api/account/update", (req, res) => {
const { body } = req;
// Validating and Checking Email
if (body.email) {
var email = body.email;
email = email.toLowerCase();
email = email.trim();
body.email = email;
User.find(
{
email: body.email
},
(err, previousUsers) => {
if (previousUsers.length > 0) {
return res.send({
success: false,
message:
"Error: There is already another account with that email address"
});
} else {
}
}
);
}
// Validating Names Function
function checkName(name) {
var alphaExp = /^[a-zA-Z]+$/;
if (!name.match(alphaExp)) {
return res.send({
success: false,
message: "Error: Names cannot contain special characters or numbers"
});
}
}
checkName(body.firstName);
checkName(body.lastName);
// Making sure that all fields cannot be empty
if (!body.email && !body.firstName && !body.lastName) {
return res.send({
success: false,
message: "Error: You cannot submit nothing"
});
}
// Getting User ID from the current session
UserSession.findById(body.tokenID, function(err, userData) {
// Finding User ID using the current users session token
if (userData.isDeleted) {
return res.send({
success: false,
message:
"Error: Session token is no longer valid, please login to recieve a new one"
});
}
// Deleting the token ID from the body object as user table entry doesnt store tokens
delete body.tokenID;
// Finding the user profile and updating fields that are present
User.findByIdAndUpdate(userData.userId, body, function(err, userInfo) {
if (!err) {
return res.send({
success: true,
message: "Success: User was updated successfully"
});
}
});
});
});
This is the call that I am doing to the backend of the site:
onUpdateProfile: function(fieldsObj) {
return new Promise(function(resolve, reject) {
// Get Session Token
const obj = getFromStorage("the_main_app");
// Defining what fields are getting updated
fieldsObj.tokenID = obj.token;
// Post request to backend
fetch("/api/account/update", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(fieldsObj)
})
.then(res => {
console.log("Verify Token - Res");
return res.json();
})
.then(json => {
console.log("Verify Token JSON", json);
if (json.success) {
window.location.href = `/manage-account?success=${json.success}`;
} else {
window.location.href = `/manage-account?success=${json.success}`;
}
});
});
}
Here is my error message that I am getting:
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at ServerResponse.header (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\express\lib\response.js:767:10)
at ServerResponse.send (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\express\lib\response.js:267:15)
at ServerResponse.send (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\express\lib\response.js:158:21)
at C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\routes\api\account.js:270:22
at C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\mongoose\lib\model.js:4641:16
at process.nextTick (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\mongoose\lib\query.js:2624:28)
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
[nodemon] app crashed - waiting for file changes before starting...
Can anyone help me with this?
EDIT
I have changed my code, this seems to now work however I feel like its a little messy when put together. Any refactoring tips?
Code:
app.post("/api/account/update", (req, res) => {
// Preform checks on data that is passed through
const { body } = req;
var messages = {
ExistedUser:
"Error: There is already another account with that email address",
NameFormat: "Error: Names cannot contain special characters or numbers",
BlankInputs: "Error: You cannot submit nothing",
accountLoggedOut:
"Error: Session token is no longer valid, please login to recieve a new one",
successfullyUpdated: "Success: User was updated successfully"
};
var usersFound;
if (body.email) {
var email = body.email;
email = email.toLowerCase();
email = email.trim();
body.email = email;
User.find(
{
email: body.email
},
(err, UserCount) => {
usersFound = UserCount;
}
);
}
function capitalize(text) {
return text.replace(/\b\w/g, function(m) {
return m.toUpperCase();
});
}
if (body.firstName) {
body.firstName = capitalize(body.firstName);
}
if (body.lastName) {
body.lastName = capitalize(body.lastName);
}
//Making sure that all fields cannot be empty
if (!body.email && !body.firstName && !body.lastName) {
return res.send({
success: false,
message: messages.BlankInputs
});
}
// Getting User ID from the current session
UserSession.findById(body.tokenID, function(err, userData) {
// Finding User ID using the current users session token
if (userData.isDeleted) {
return res.end({
success: false,
message: messages.accountLoggedOut
});
}
if (userData) {
// Deleting the token ID from the body object as user table entry doesnt store tokens
delete body.tokenID;
// Finding the user profile and updating fields that are present
User.findByIdAndUpdate(userData.userId, body, function(err, userInfo) {
if (userInfo) {
if (!usersFound.length > 0) {
return res.send({
success: true,
message: messages.successfullyUpdated
});
} else {
return res.send({
success: false,
message: messages.ExistedUser
});
}
}
});
}
});
});
You're calling res.send() twice. res.send() ends the process. You ought to refactor such that you call res.write() and only call res.send() when you're done.
This StackOverflow link describes the difference in more detail. What is the difference between res.send and res.write in express?
I believe this is happening, as you're trying to send a response after the first / initial response has already been sent to the browser. For example:
checkName(body.firstName);
checkName(body.lastName);
Running this function twice is going to try and yield 2 different "response" messages.
The product of a single route, should ultimately be a single response.
Thanks for all your help on this issue.
Here is my final code that allowed it to work.
I have also tried to "refactor" it too. Let me know if you'd do something else.
app.post("/api/account/update", (req, res) => {
const { body } = req;
console.log(body, "Logged body");
// Defining objects to be used at the end of request
var updateUserInfo = {
userInfo: {},
sessionToken: body.tokenID
};
var hasErrors = {
errors: {}
};
// Checking that there is at least one value to update
if (!body.email && !body.firstName && !body.lastName) {
var blankError = {
success: false,
message: "Error: You cannot change your details to nothing"
};
hasErrors.errors = { ...hasErrors.errors, ...blankError };
} else {
console.log("Normal Body", body);
clean(body);
console.log("Cleaned Body", body);
updateUserInfo.userInfo = body;
delete updateUserInfo.userInfo.tokenID;
}
// Function to check if object is empty
function isEmpty(obj) {
if (Object.keys(obj).length === 0) {
return true;
} else {
return false;
}
}
// Function to remove objects from body if blank
function clean(obj) {
for (var propName in obj) {
if (obj[propName] === "" || obj[propName] === null) {
delete obj[propName];
}
}
}
// Checking and Formatting Names Given
function capitalize(text) {
return text.replace(/\b\w/g, function(m) {
return m.toUpperCase();
});
}
if (body.firstName) {
body.firstName = capitalize(body.firstName);
}
if (body.lastName) {
body.lastName = capitalize(body.lastName);
}
// Checking and formatting email
if (body.email) {
body.email = body.email.toLowerCase();
body.email = body.email.trim();
// Checking for email in database
User.find({ email: body.email }, (err, EmailsFound) => {
if (EmailsFound.length > 0) {
var EmailsFoundErr = {
success: false,
message: "There is already an account with that email address"
};
hasErrors.errors = { ...hasErrors.errors, ...EmailsFoundErr };
}
});
}
// Getting User Session Token
UserSession.findById(updateUserInfo.sessionToken, function(err, userData) {
// Finding User ID using the current users session token
if (userData.isDeleted) {
var userDeletedError = {
success: false,
message:
"Your account is currently logged out, you must login to change account details"
};
hasErrors.errors = { ...hasErrors.errors, ...userDeletedError };
} else {
// Finding the user profile and updating fields that are present
User.findByIdAndUpdate(
userData.userId,
updateUserInfo.userInfo,
function(err, userInfo) {
// userInfo varable contains user db entry
if (err) {
var updateUserError = {
success: false,
message: "Error: Server Error"
};
hasErrors.errors = {
...hasErrors.errors,
...updateUserError
};
}
if (isEmpty(hasErrors.errors)) {
res.send({
success: true,
message: "Success: You have updated your profile!"
});
} else {
res.send({
success: false,
message: hasErrors.errors
});
}
}
);
}
});
});

Jquery Terminal register & login

I have question, i want user register then login but here it's error anyone can help me ? i saw the documentation . here is link of the documentation jquery termi[jquery terminal]1nal
here is my script:
if (command == 'register') {
term.push(function(command, term) {
term.pause();
$.ajax({
url: "register.php",
type: "post",
data: {data_register : command },
success: function (msg) {
term.echo(yellow('Data Saved Successfully !'));
term.resume();
},
error: function(jqXHR, textStatus, errorThrown) {
term.resume();
}
});
},
{
prompt: " > "
});
} else if (command == 'login'){
login: function(user, password, callback) {
if (user == 'demo' && password == 'secret') {
callback('SECRET TOKEN');
} else {
callback(null);
}
}
}
this line's error :
else if (command == 'login'){
login: function(user, password, callback) {
if (user == 'demo' && password == 'secret') {
callback('SECRET TOKEN');
} else {
callback(null);
}
}
}
Thank you
You have invalid JavaScript you have label and function declaration, which should be put in an object like this:
var x = {
login: function() {
}
};
which should be part of object in second argument which is options object.
.terminal(function(command) {
if (command === 'register') {
}
}, {
login: function(...) {
...
}
});
and for your exact problem on having login command, that login you in, you need to invoke login method like this:
} else if (command == 'login'){
term.login(function(user, password, callback) {
// to get the token you should send user and password to the server
if (user == 'demo' && password == 'secret') {
callback('SECRET TOKEN');
} else {
callback(null);
}
});
} else if (term.token()) {
// here are commands that will only work after user login
// but you need to know that user may add token in developer tools
// so you should use additional check if token is valid by sending token
// to the server, or if you're invoking command on the server then just
// send the token and validate it there
} else {
term.error('invalid command');
}

Meteor : Stop login if email is unverified

In my meteor.js app I only want verified users signing in. They must click the link in their email first.
I don't see any official mention of this in the documentation. Any ideas?
client javascript
Template.login.events({
'submit #login-form' : function(e,t){
e.preventDefault();
var email = t.find('#email').value;
var password = t.find('#password').value;
Meteor.loginWithPassword(email, password, function(error){
if (error){
console.log(error);
}
else{
console.log("success");
}
});
return false;
}
});
There are some stackoverflow posts but these only cover blocking unverified users from viewing certain pages:
Meteor: Block access to application if user's email is not verified
What you could do is check for the verified token inside the Accounts db.
Something of this sort:
if (Meteor.isServer) {
Meteor.methods({
'get_users_by_email': function(email) {
return Users.findOne({ emails.address: email }).fetch()[0].verified;
}
});
}
if (Meteor.isClient) {
a = Meteor.call('get_users_by_email', 'email-entered-by-user');
}
Then, you can check whether a is true or false.
When a is false, you could login the user, and when it is true, you can prevent the login by showing an error or whateever you want to tell people who have verified email adresses.
/lib/methods.js
Meteor.startup(function() {
checkEmailVerification: function(email) {
found_user = Meteor.users.findOne({ 'emails.address' : email })
if(found_user){
if(found_user.emails[0].verified == true){
return "verified";
}else{
return "unverified";
}
}else{
return "notfound";
}
}
});
});
/client/login.js
Template.login.events({
'submit #login' : function(event, t){
event.preventDefault();
var email = t.find('#email').value;
var password = t.find('#password').value;
Meteor.call('checkEmailVerification', email, function(error,data){
if (data == "verified"){
Meteor.loginWithPassword(email, password, function(err){
if (err){
FlashMessages.sendError("Either email or password is incorrect");
}
else{
FlashMessages.sendSuccess("Logged in");
}
});
}else if(data == "unverified"){
FlashMessages.sendError("Check your email for a verification link");
}else{
FlashMessages.sendError("Either email or password is incorrect");
}
});
}
});

Categories

Resources