Meteor recover password and change password - javascript

I am new to meteor and I am trying to do recover password and change password in Meteor. I will post below the code I have used to do this. I do get the template rendered, but the passwords do not change. Can anyone please help me with this? I am using the package accounts-password.
Custom-useraccounts.html:
<template name="RecoverPassword">
<form id="set-new-password">
<label for="new-password">New Password</label>
<input type="password" id="new-password" placeholder="Try not to forget this one.">
<input type="submit" value="Set New Password">
<p id="form-messages"></p>
</form>
<form id="forgot-password">
<label for="user-email">Email</label>
<input type="text" id="user-email" placeholder="Email">
<input type="submit" value="Get Reset Password Instructions">
<p id="form-messages"></p>
</form>
</template>
<template name="ChangePassword">
<form id="change-password">
<label for="current-password">Current Password</label>
<input type="password" id="current-password" placeholder="Current Password">
<label for="new-password">New Password</label>
<input type="password" id="new-password" placeholder="New Password">
<label for="new-password-repeated">Repeat New Password</label>
<input type="password" id="new-password-repeated" placeholder="Repeat New Password">
<input type="submit" value="Update Password">
<p id="form-messages"></p>
</form>
</template>
custom user-accounts.js:
if (Meteor.isServer) {
Template.RecoverPassword.events({
'submit #change-password': function(event, template) {
var currentPassword,
newPassword,
newPasswordRepeated;
currentPassword = template.find('#current-password');
newPassword = template.find('#new-password');
newPasswordRepeated = template.find('#new-password-repeated');
if (newPassword !== newPasswordRepeated) {
template.find('#form-messages').html("The new passwords don't match!");
return false;
}
if (Meteor.isServer) {
if (Accounts._resetPasswordToken) {
Session.set('resetPasswordToken', Accounts._resetPasswordToken);
}
Template.RecoverPassword.helpers({
resetPassword: function() {
return Session.get('resetPasswordToken');
}
});
Template.RecoverPassword.events({
'submit #forgot-password': function(event, template) {
event.preventDefault();
var email = template.find('#user-email'),
message;
alert(email);
if (email) {
Accounts.forgotPassword(email);
message = 'Sent a reset password link to ' + email + '.';
} else {
message = 'Please enter a valid email address.'
}
template.find('#form-messages').html(message);
return false;
},
'submit #set-new-password': function(event, template) {
event.preventDefault();
// Proper decoupled validation would be much nicer than this
var password = template.find('#new-password').value,
passwordTest = new RegExp("(?=.{6,}).*", "g");
if (passwordTest.test(password)) {
Accounts.resetPassword(
Session.get('resetPasswordToken'),
password,
function(error) {
if (err) {
template.find('#form-messages').html('There was a problem resetting your password.');
} else {
Session.set('resetPasswordToken', null);
}
});
} else {
template.find('#form-messages').html('Your password is too weak!');
}
return false;
}
});
}
I have already removed the insecure and autopublish options and I have published the userdata. I just cannot understand why template to change password does not work.

Well, the issue is you're running that code on the server with if (Meteor.isServer)
All your client code needs to be in if (Meteor.isClient) which is anything template level. You also get that for free if it's in a folder called client.

Related

is there any way to remove the default error from input type email when user enter the incorrect email address?

is there any way to remove the default error from input type email when the user enters the incorrect email address? as I'm working on form validation with an email address. i can see default error from on input email but not on my console.
<div class="registration-box">
<form id="form-data">
<input
type="email"
placeholder="Email Address"
class="email-id"
id="email-data"
/>
<span class="btn-box"
><input type="submit" class="submit" value="submit" /></span>
</form>
</div>
<div class="error-msg">Please provide a valid email</div>
const formData = document.getElementById("form-data");
const emailAdd = document.querySelector("input[type='email']");
const emailReg = /^[(\w\d\W)+]+#[\w+]+\.[\w+]+$/i;
formData.addEventListener("submit", (e) => {
e.preventDefault();
if (emailReg.test(emailAdd.value)) {
console.log("correct");
} else {
console.log("error");
}
});
You can accomplish this by disabling the form authentication, when you do this tho you need to make sure that your authentication is water proof.
We all know how ugly the stock validation is by default, and you can disable this by adding novalidate to your <form>
Here is a example of the validation that shows the user a custom error message if email.checkValidity() returns false
let email = document.getElementsByClassName("email-field")[0];
function validate_email() {
if (!email.checkValidity()) {
document.getElementById("error").innerHTML = "E-mail is not correct";
return false;
} else {
document.getElementById("error").innerHTML = "";
return true;
}
}
console.log("email " + email.value + " " + email.checkValidity());
<form onsubmit="return validate_email(this)" novalidate>
<input type="email" placeholder="Email Address" class="email-field" required>
<p id="error" style="color: red;"></p>
<input type="submit" onsubmit="return validate_email(this)">
</form>
Hope this helped, if it didn't please let me know, and I will see what I can do to further help you.

Delay of updating with if meteor/blaze statements

I created a mini application with custom login always in the same page, to explain better I have a main page with the login and registration and when I do the login/registration I remain on the same page and where was the login form appear a "Welcome Back" panel.
The problem is that when I try to reload the page with F5 I get for like 2 seconds the old login form and then appear the "Welcome Back" panel. I've used the If statements of Blaze to manage the check of the current user logged in as we can see:
<template name="login">
{{#if currentUser}}
<div class=" card mb-4 shadow-sm">
<div class="card-header">
<h4 class="my-0 font-weight-normal">Welcome Back</h4>
</div>
<div class="card-body">
TEST
</div>
</div>
{{else}}
<div id="panel-login" class=" card mb-4 shadow-sm">
<div class="card-header">
<h4 class="my-0 font-weight-normal">Login Form</h4>
</div>
<div class="card-body">
<form class="login-form">
<div class="form-group">
<label for="InputEmail">Email address</label>
<input type="email" class="form-control" name="email" id="InputEmailLogin" aria-describedby="emailHelp" placeholder="Enter email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="InputPassword">Password</label>
<input type="password" name="password" class="form-control" id="InputPasswordLogin" placeholder="Password">
</div>
<button type="submit" class="btn btn-primary">Login</button>
<span>or Create an account</span>
</form>
</div>
</div>
<div id="panel-register" class=" card mb-4 shadow-sm">
<div class="card-header">
<h4 class="my-0 font-weight-normal">Register Form</h4>
</div>
<div class="card-body">
<form class="register-form">
<div class="form-group">
<label for="InputEmail">Email address</label>
<input type="email" class="form-control" name="email" id="InputEmail" aria-describedby="emailHelp" placeholder="Enter email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div class="form-group">
<label for="InputPassword">Password</label>
<input type="password" name="password" class="form-control" id="InputPassword" placeholder="Password">
</div>
<div class="form-group">
<label for="InputPassword">Repeat Password</label>
<input type="password" name="password2" class="form-control" id="InputPasswordConfirm" placeholder="Repeat Password">
</div>
<button type="submit" class="btn btn-primary">Register</button>
<span>or Login</span>
</form>
</div>
</div>
{{/if}}
</template>
That's my JS file where I manage the entire events of login/registration system:
Template.login.events({
'click .register-link': function() {
$('#panel-login').hide();
$('#panel-register').show().addClass("animated fadeIn");
},
'click .login-link': function() {
$('#panel-register').hide();
$('#panel-login').show().addClass("animated fadeIn");
},
// Registration
'submit .register-form': function(event) {
var email = trimInput(event.target.email.value);
var password = trimInput(event.target.password.value);
var password2 = trimInput(event.target.password2.value);
if(isNotEmpty(email) && isNotEmpty(password) && isNotEmpty(password2)
&& isEmail(email) && areValidPasswords(password,password2)) {
Accounts.createUser({
email: email,
password: password,
profile: {
userType: 'Normal'
}
}, function(err) {
if(err) {
sAlert.error("There was an error with the registration, try again!");
} else {
sAlert.success("Account Created! You are now logged in");
}
});
}
// Prevent Submit
return false;
},
// Login
'submit .login-form': function(event) {
var email = event.target.email.value;
var password = event.target.password.value;
Meteor.loginWithPassword(email, password, function(err) {
if(err) {
event.target.email.value = email;
event.target.password.value = password;
sAlert.error("There is an error with your login, try again!");
} else {
sAlert.success("You are now logged in!");
}
})
// Prevent Submit
return false;
}
});
Template.login.helpers({
ifLogged: function(user) {
if(user != null) {
$('#panel-login').hide();
}
}
});
// Trim the input
var trimInput = function(val) {
return val.replace(/^\s*|\s*$/g, "");
};
// Check for empty fields
isNotEmpty = function(value) {
if(value && value !== "") {
return true;
}
sAlert.error('Please fill all the fields');
return false;
};
// Validating Email
isEmail = function(value) {
var filter = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if(filter.test(value)) {
return true;
}
sAlert.error("Invalid email, please use a valid email address");
return false;
};
// Check passwords fields
isValidPassword = function(password) {
if(password.length < 6) {
sAlert.error("Password must be at least 6 characters");
return false;
}
return true;
}
// Check confirmation password
areValidPasswords = function(password, confirm) {
if(!isValidPassword(password)) {
return false;
}
if(password !== confirm) {
sAlert.error("Password do not match");
return false;
}
return true;
};
Here there's a GIF to show you the problem:
https://i.gyazo.com/120efc183793d4d1adc5fb518e01c09c.mp4
Thanks if someone can help me.
If you just wanna to git rid of that flick then you can implement loading on Meteor.loggingIn as sample below, alter it with your use case i.e wrap it in a template Helper and replace that helper with currentUser
if (Meteor.loggingIn()) {
return 'loading';
} else if (Meteor.user()) {
return 'home';
} else {
return 'signin';
}

how to create new user based on input values

I have a problem and it's hard, too hard for me as a beginner. Can you please help me. I know this is kinda strange creating this with javascript but it's just my own project, nothing i will put on web. But i need this problem solved by using pure Vanilla Javascript, i have
users as shown below on .js and i have a page where i need to create i new user that can be logged in as same as other two(admin and guest), i need another guest user and created based on input values...Thanks in advance, i am still learning and comments would be appreciated as well..
var el = document.getElementById("login");
if (el) {
el.addEventListener('click', state);
}
function state() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if (username == "admin" && password == "admin") {
sessionStorage.setItem("isAdmin", "yes");
alert("You are logged in as ADMIN !");
window.location.href = "../index.html";
} else if (username == "guest" && password == "guest") {
sessionStorage.setItem("isAdmin", "no");
alert("You are logged in as GUEST !");
window.location.href = "../index.html";
} else {
alert("Incorrect username or password, try again !")
}
}
<header>
<div class="container">
<div id="branding">
<h1><span id="logo">mov</span>BLANK</h1>
</div>
<nav>
<ul>
<li>Home</li>
<li><a id="newprojection" href="newprojection.html">New projection</a></li>
<li><a id="buyticket" href="buyticket.html">Buy a ticket</a></li>
<li class="current"><a id="newuser" href="newuser.html">New user</a></li>
<li><a id="loginbtn" href="login.html">Log in</a></li>
<li>
<a id="nameofuser" href="#"></a>
</li>
</ul>
</nav>
</div>
</header>
<div class="container">
<form>
<p>Username</p>
<input type="text" name="username" required>
<p>Password</p>
<input type="password" name="password" required>
<p>Repeat Password</p>
<input type="password" name="password" required>
<p>Function(admin/guest)</p>
<input type="text" name="function" required>
<a id="adduser" href="#">Add User</a>
</form>
</div>
you can save two data: value and key so add this function in your code.
function saveData() {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
if(!sessionStorage.getItem(username) == username) {
sessionStorage.setItem(username, password);
}else {
alert(username + "already registered");
}
}
update this
<input type="text" name="username" required id="username">
<p>Password</p>
<input type="password" name="password" required id="password">
<p>Repeat Password</p>
<input type="password" name="password" required>
<p>Function(admin/guest)</p>
<input type="text" name="function" required>
<a id="adduser" href="#" onclick="saveData();">Add User</a>
This is the logic, I hope I have helped
Try creating an array of valid users, rather than using if-else statements to check against each individual user (which can't be adapted to additional users).
const users = [
{ username: 'admin', password: 'admin' },
{ username: 'guest', password: 'guest' },
];
Then when you want to create a new user, push to that array. Verify logins with with:
function state() {
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const foundUser = users.find(user => user.username === username && user.password === password);
if (!foundUser) {
console.log('Invalid user!');
} else {
// Log the user in
}
}
Problem is, your current code validates a user login attempt (for which there isn't a button for), which can't (or shouldn't) be the same form as the form used to register, at least not without changing things around significantly.
I made a working example, see below. The example is just for testing/learning purposes. I would recommend you to validate user and password using http requests and preventing sql injections.
PS: here is jsfiddle: https://jsfiddle.net/xdLey6cp/24/
PS2: you can use sweet alert instead of alert: https://sweetalert.js.org/guides/
<input type="text" id="txt_user" placeholder="user">
<!--you should use type=password here, but set as text for test purposes-->
<input type="text" id="txt_password" placeholder="password">
<input type="submit" id="createuser" value="create user">
<input type="submit" id="validateuser" value="validate new user">
<script>
//adding event handlers
document.querySelector('#createuser').onclick = create_user;
document.querySelector('#validateuser').onclick = validate_user;
function create_user()
{
//assign values for username and password
var username = document.querySelector("#txt_user").value;
var password = document.querySelector("#txt_password").value;
//using sessionstorage to keep user and password values
sessionStorage.setItem("username", username);
sessionStorage.setItem("password", password);
alert('new user is created');
}
function validate_user()
{
//getting previously recorded username and password
var recorded_username = sessionStorage.getItem("username");
var recorded_password = sessionStorage.getItem("password");
//assign values for username and password
var username = document.querySelector("#txt_user").value;
var password = document.querySelector("#txt_password").value;
//doing it as simple as possible, no filters (trim, lowercase) at all
if (username==recorded_username && password==recorded_password)
{alert('user and password are valid');}
else
{alert('validation error');}
}
</script>

How to use $asyncValidators with angularjs and set a warning message in the HTML

This is my first bigger form with validations and etc.
I've created a Registration form and I'm using ng-messages for validation. The problem is that I need to validate the username, does it already exist in the JSON server that we are using or it's available. Of course, if it's taken the warning pops out in the HTML where the username input is, if it's available the submit button is no more disabled (because the form will be $valid) and the user can register. I want to use angular-sanitize because I found this (I don't know if they are related):
ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
var value = modelValue || viewValue;
// Lookup user by username
return $http.get('/api/users/' + value).
then(function resolved() {
//username exists, this means validation fails
return $q.reject('exists');
}, function rejected() {
//username does not exist, therefore this validation passes
return true;
});
};
Here is the code I use now (reg form, controller and service):
// Controller:
export default class registerPageController {
constructor(userService, authenticationService, $location) {
this.register = "Register";
this.userService = userService;
this.$location = $location;
this.authenticationService = authenticationService;
this.hasLoggedIn = false;
}
onSubmit(user) {
let self = this;
let {
name,
age,
email,
username,
password
} = user;
self.userService.register(name, age, email, username, password).then((res) => {
self.userService.login(username, password).then(function (response) {
let data = response.data;
if (data.length) {
let user = data[0];
self.hasLoggedIn = true;
self.authenticationService.setCredentials(username, password);
self.$location.path('/');
}
});
})
.catch(err => {
// WHAT TO PUT HERE AFTER THE USERNAME EXIST VALIDATION ?
})
}
}
// Service:
export class UserService {
constructor($http) {
this.$http = $http;
}
login(username, password) {
return this.$http({
method: 'GET',
url: 'http://localhost:3000/users',
params: {
username: username,
password: password
}
});
}
register(name, age, email, username, password) {
return this.$http({
method: 'POST',
url: 'http://localhost:3000/users',
data: {
name: name,
age: age,
email: email,
username: username,
password: password
}
});
}
// SHOULD I PUT HERE THE USERNAME EXIST VALIDATION LOGIC ?
}
<div class="container main-content">
<form class="registrationForm" name="registerForm" ng-submit="register.onSubmit(register.user)" novalidate="novalidate">
<!-- Enter Name -->
<div class="form-group">
<label for="name" class="control-label"><span id="reqInfo">*</span> Name</label>
<input type="text" name="name" class="form-control" ng-model="register.user.name" ng-pattern="/[a-zA-Zа-яА-Я]+/" id="name"
required="" placeholder="Example: Petar Petrov">
<div ng-messages="registerForm.name.$error" ng-show="registerForm.name.$touched" style="color:maroon" role="alert">
<div ng-message="required">Your name is required</div>
</div>
</div>
<!-- User Age-->
<div class="form-group">
<label for="age" class="control-label"><span id="reqInfo">*</span> Age</label>
<input type="number" name="age" class="form-control" ng-model="register.user.age" ng-min="18" min="18" id="age" required=""
placeholder="Enter your age">
<div ng-messages="registerForm.age.$error" ng-show="registerForm.age.$touched" style="color:maroon" role="alert">
<div ng-message="min">You must be at leats 18 years old</div>
</div>
</div>
<!-- Enter E-mail -->
<div class="form-group">
<label for="email" class="control-label"><span id="reqInfo">*</span> E-mail</label>
<input type="email" name="email" class="form-control" ng-model="register.user.email" ng-pattern="/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+#)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+#)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%#\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/"
id="email" required="" placeholder="Example: mail#mail.net">
<div ng-messages="registerForm.email.$error" ng-show="registerForm.email.$touched" style="color:maroon" role="alert">
<div ng-message="required">Your valid e-mail is required</div>
</div>
<br>
<!-- Enter Username -->
<div class="form-group">
<label for="username" class="control-label"><span id="reqInfo">*</span> Username</label>
<input type="text" name="username" ng-minlength="5" ng-maxlength="20" class="form-control" ng-model="register.user.username"
ng-pattern="/^[A-Za-z0-9_]{1,32}$/" ng-minlength="7" id="username" required="" placeholder="Enter your username">
<div ng-messages="registerForm.username.$error" style="color:maroon" role="alert">
<div ng-message="minlength">Your Username must be between 7 and 20 characters long</div>
</div>
<br>
<!-- Enter Password -->
<div class="form-group">
<label for="password" class="control-label"><span id="reqInfo">*</span> Password</label>
<input type="password" name="password" class="form-control" ng-model="register.user.password" ng-minlength="7" id="password"
required="" placeholder="Enter your password">
<div ng-messages="registerForm.password.$error" style="color:maroon" role="alert">
<div ng-message="minlength">You Password must be at least 7 symbols long</div>
</div>
</div>
<!-- Register button -->
<div class="form-group">
<button class="btn btn-primary" type="submit" ng-disabled="!registerForm.name.$valid || !registerForm.age.$valid || !registerForm.email.$valid || !registerForm.username.$valid || !registerForm.password.$valid">Register</button>
</div>
<p>Fields with <span id="reqInfo">*</span> must be filled.</p>
</form>
</div>
Important is to know that I have being told explicitly to write it in ES6.
I have problem with the logic so look at my code and please fill it for me so I can use it and most important - learn it :S
Thank you so so much in advance!
I have implemented a directive for different kind of validations (sync Async), and it supports warning as well.
You may check it from
`https://plnkr.co/2WQHOo`
If this is what you needed and need more information, let me know I will try my best to answer.

Display error message depending on if user is disabled or if input is invalid using JS/HTML

I want to display an error message under the 'Email Address' input if the user is disabled and display a separate error message if the user is invalid under the 'Password' input. When debugging I found that if a user is disabled the "Status code is 503" and if the input is invalid the "Status code is 400".
HTML
<md-content id="login" layout="column" layout-align="center center" class="inputdemoErrors">
<div flex="25"></div>
<p class="m0">project</p>
<form id="loginForm">
<md-input-container>
<label for="username">Email Address</label>
</md-input-container>
<md-input-container class="email-field">
<input name="username" id="username" type="email" class="validate" ng-model="username" enter-key="submitLogin()" autocomplete="off" required>
<div ng-show="disabled" ng-messages="loginForm.username.$error" role="alert">
<div ng-message="required">User Account is Disabled</div>
</div>
</md-input-container>
<md-input-container>
<label for="password">Password</label>
</md-input-container>
<md-input-container class="password-field">
<input name="password" id="password" type="password" class="validate" ng-model="password" enter-key="submitLogin()" autocomplete="off" required>
<div ng-show="invalid" ng-messages="loginForm.password.$error" role="alert">
<div ng-message="required">Invalid Email or Password</div>
</div>
</md-input-container>
<a class="waves-effect waves-light btn-large" style="width: 100%; margin: 0; background-color: #29B6F6;" ng-click="submitLogin()">Login</a>
</form>
</md-content>
JS
angular
.module('login')
.controller('LoginCtrl', LoginCtrl);
function LoginCtrl($scope, $location, SecService, RecService, Service) {
var vm = this;
vm.ctrlName = 'LoginCtrl';
$scope.submitLogin = function() {
$scope.invalid = $scope.loginForm.$invalid;
if($scope.invalid) {
return;
}
else
$scope.dataLoading = true;
var creds = {
username: $scope.username,
password: $scope.password
};
SecService.login(creds).then(function (response) {
if (response.success) {
RecService.connect();
SecService.setCredentials($scope.username, $scope.password);
Service.loadCurrentUser();
$location.path('/main');
}
if (response = 503)
{
$scope.disabled = $scope.loginForm.$disabled;
if ($scope.invalid) return invalid;
}
if (response = 400)
{
$scope.invalid = $scope.loginForm.$invalid;
if ($scope.invalid) return invalid;
}
});
};
}
}());
I am trying to display "User Account is Disabled" if the user is disabled (503), and "Email or Password is Invalid" if they have an invalid input (400). This should happen when the login button is clicked.
Hard to give a good answer without knowing what functionality you want with the ng-messages.
If you omit ng-messages:
<div ng-show="showDisabled">
User Account is Disabled
</div>
<div ng-show="showInvalid">
Invalid Email or Password
</div>
The following doesn't look right, so remove it for now:
if (response = 503)
{
$scope.disabled = $scope.loginForm.$disabled;
if ($scope.invalid) return invalid;
}
if (response = 400)
{
$scope.invalid = $scope.loginForm.$invalid;
if ($scope.invalid) return invalid;
}
It doesn't look like the return values are used anywhere and it should be response === x, not response = x.
Replace with:
$scope.showDisabled = response === 503;
$scope.showInvalid = response === 400;
Another note, if you need to access the form like this:
ng-messages="loginForm.password.$error"
The form needs a name:
<form name="loginForm">
Instead of id:
<form id="loginForm">

Categories