Meteor: resetPassword email link behavior - meteor

I'm trying to implement the "reset password" functionality in my Meteor app. I have a very simple implementation of it based on this tutorial: Julien's tutorial on gentlenode
There are several examples floating around that use this same basic approach. I did mine almost exactly like Julien's but I used only one template; I use an {{#if}} in my template that displays the 'reset password' form, if my session variable sResetPassword is not falsey. (I don't know how the correct template is supposed to get displayed in Julien's example and it doesn't work for me as it is written -- the template doesn't change.)
Here's the critical piece of code. Two different methods that both work on my local app, but neither one works on my hosted (modulus) app.
/* method one
if (Accounts._resetPasswordToken) {
Session.set('sResetPassword', Accounts._resetPasswordToken);
}
/* method two
Accounts.onResetPasswordLink( function(token) {
Session.set('sResetPassword', token);
});
On my deployed version (Modulus), the link opens up my app and just goes straight to the start screen. When I check the value of my sResetPassword session var, it's undefined, so somehow the value of the token never gets put into the var.
While we're on the subject, does anyone know how you are supposed to get the correct template to load when you use a separate template for the reset password form?

Here is how it works for us. Code:
var token, done;
Accounts.onResetPasswordLink(function (t, d)
{
token = t;
done = d;
setTimeout(()=>Router.go("reset_password"), 0);
});
Template["reset_password"].events({
"click #resetBtn": function (event:Event, instance:Blaze.TemplateInstance)
{
var password1: string = instance.$("#input_password1").val();
var password2: string = instance.$("#input_password2").val();
console.log(password1, password2);
if (password1 != password2)
{
return;
}
Accounts.resetPassword(token, password1, ()=>
{
done();
Router.go("somewhere");
});
}
});
Template:
<template name="reset_password">
<form data-parsley-validate>
<div class="input-field">
<input id="input_password1" type="password" class="validate" data-parsley-trigger="keyup" data-parsley-minlength="6" data-parsley-minlength-message = "Please provide a password that is at least a 6 characters long." required>
<label for="input_password1">New Password</label>
</div>
<div class="input-field">
<input id="input_password2" type="password" class="validate" data-parsley-trigger="keyup" data-parsley-minlength="6" data-parsley-minlength-message = "Please provide a password that is at least a 6 characters long." required>
<label for="input_password2">Again</label>
</div>
<button id="resetBtn" class="waves-effect btn">Reset Password</button>
</form>

OK, for whatever reason, replacing iron-router with flow-router fixed this issue for me. I created a new app with only the login and reset password functionality and it worked fine. I added iron-router and again it worked, but only dev mode. When I ran it in production mode, the problem returned. Replaced iron-router with flow-router (in both the test app and my full app) and now the problem is gone. The email link works as expected in both modes.

Related

Cypress submitting form with preventDefault

I am having trouble using Cypress.
There are 2 problems I'm currently having.
A form with preventDefault is being submitted and the page is refreshing.
I have to .click() and input before I can .type() into it.
--
I have a form that has preventDefault, and you can see from the test that it submites the form, which adds a empty query string to the url, and none of my error handling messages are shown. This doesn't actually happen when I use the app myself.
it('requires email', () => {
cy.visit('/sign-in')
cy.get('form').contains('Sign in').click()
cy.get('.errors').should('contain', 'Email is required.')
})
I am using Svelte/Sapper as my front-end.
Form:
<form on:submit|preventDefault={handleSubmit}>
<Input label="Email" type="email" bind:value={email} />
<Input label="Password" type="password" bind:value={password} />
<Button text="Sign in" />
</form>
The second issue is that I have to .click() and input in my test before I can .type() into it.
I have to do this:
cy.get('#email').click().type('user#example.com{enter}')
Instead of this:
cy.get('#email').type('user#example.com{enter}')
I am not sure why this is happening. If I don't click the field, it says the field may have the attribute disabled, which it doesn't. When I test it myself, I don't see any issues, and the dom snapshots in Cypress don't reveal anything unusual.
Perhaps it has to do with autofill?
Has anyone run into these problems?
The issue with Sapper is that it is SSR, so the app was not hydrated before Cypress started running tests, which was causing a whole bunch of issues.
The solution was to tell Cypress to wait until the app was hydrated. This was accomplished by setting an attribute in the return to the promise from sapper.start and then overwriting the Cypress visit command.
client.js:
sapper.start({
target: document.querySelector("#app"),
}).then(() => {
document.body.setAttribute('hydrated', '')
})
Cypress commands:
Cypress.Commands.overwrite('visit', (orig, url, options) => {
orig(url, options)
cy.get('body[hydrated]').should('have.length', 1)
})
Now everything works and tests are passing.

How To Update Database Using Angular Material Reactive Form And Restful API

Let Me take famous Book Example To explain My question.
I have a angular material reactive form build based on Book Model in my BookService.ts. When I change some field In this form and Submit it to my back end to update according record using Angular HttpClient PUT method It is not updating my database and comes back with and error. When I debug it, It shows ID is not defined, When I console.log(BookForm.value) I get This out put: {$key: 1234, Title: "Book Title1", Topic: "Topic1"} , No need to say my Angular HttpClient PUT Restful API needs that ID in order to be able to update that particular record in My Database table. Bellow Is My Simplified Mocked Code To Explain It.
BookModel.ts File, My Model
export interface Book{
ID: number;
Title: string;
Topic: string;
}
BookService.ts File, My Service
BookForm: FormGroup = new FormGroup({
$key: new FormControl(null),
Title: new FormControl('', Validators.required),
Topic: new FormControl('', Validators.required),
});
UpdateBook(bookObj: Book): Observable<Book>
{
return this.http.put<Book>(`...api/book/${bookObj.ID}`, bookObj,{
headers: new HttpHeaders({
'Content-Type: 'application/json'
})
})
}
Note: This Throw Error, ID Undefined
Book-form.component.html File
<form [formGroup] = "BookService.BookForm" class="FormCls">
<mat-grid-list rowHeight="200px">
<mat-grid-tile>
<div class="form-controles-container">
<input type="hidden" formControlName="$key" />
<mat-form-field>
<input formControlName="Title" matInput placeholder="Title*" />
<mat-error>Title Needed</mat-error>
</mat-form-field>
<mat-form-field>
<input formControlName="Topic" matInput placeholder="Topic*" />
<mat-error>Topic Needed</mat-error>
</mat-form-field>
<div class="button-row">
<button mat-raised-button color="primary" type="submit" (click)="onSubmit()">Submit</button>
</div>
</div>
</mat-grid-tile>
</mat-grid-list>
</form>
Book-form.component.ts File
onSubmit(): void
{
BookService.UpdateBook(BookService.BookForm.value).subscribe(
b => alert(`Book Updated Successfully`),
err => alert(`Exception While Updating: ${err}`)
);
}
For sure I know I need to some how convert my form value to my Book model and make sure I have that ID inside that before I pass it to my http put service. but I dont know how to do that, Im fairly new in both Angular and Typescript world and I am learning. I love reading before I ask, so went thru lots of Articles but none worked for me. For Example I tried below Article on stackoverfelow but did not work for me
Reactive Forms correctly convert Form Value to Model Object
I really Appreciate you professionals and Thank For Your Time And Help.
when you call any AbstractControl's .value method, you are gettin an object with prop: value pairs for each input in your form. As you can see, you will get an IDless object, maybe the reason is because the form has no 'ID' property, or maybe it is because the value is null (when you transform an object to JSON, all properties that have null value get deleted).
If you know the id from the HTML, you can pass it in the function
<button mat-raised-button color="primary" type="submit" (click)="onSubmit(sth.id)">
if that's not the case (I think it isn't), you could add the ID before calling your service with the .patchValue({ id: idInfo }) method that any AbstractControl has (in this case, you won't need to add a hidden input, unless you add it for another reason).
Do a patch before calling the service and it should work.
I'm not sure if this is enough info to help you, feel free to ask any questions.
edit (to add a code example):
onSubmit(): void
{
// the lines I added
const bf = BookService.BookForm;
bf.patchValue({ ID: 'anyIdYouLike' });
// what stays the same (except the bf.value shortened version)
BookService.UpdateBook(bf.value).subscribe(
b => alert(`Book Updated Successfully`),
err => alert(`Exception While Updating: ${err}`)
);
}

<script>document.cookie = "humans_21909=1"; document.location.reload(true)</script>

web API build with wordpress is showing error of
<script>document.cookie = "humans_21909=1"; document.location.reload(true)</script>
it works sometime on some network and sometime not working
I got same response for an API ending with api/register , then i change the name /register to /new_registerthen issue solved,
I think register in url is the reason for this error
First of all, clone the website using the All In One WP Migration to your local development machine. Then, check the REST API, if the same error persists. It means you have some error in your code. In my case, the REST API works perfectly fine in my local machine but shows the same HTTP 409 conflict. I contacted with the Bluehost support. They told me they have some mod_security issues. After 2 3 days, they fixed it. It worked fine after that.
I ran into the same Problem and below are the two json api have issues which are using Json API User Plugin.
http://example.com/api/get_nonce/?json=get_nonce&controller=user&method=register
http://example.com/api/user/register/?username=eww_test&email=john#domain.com&display_name=John&notify=both&seconds=100&insecure=cool
Then i move whole site to localhost and check APIs and they were working fine so i contacted host in my case hostgator.
They suggested to disable mod_security for that domain which was subdomain in my case.
And The issue has been resolved.
Tested and worked well
I am facing same issue while loading image. My image name is contact-desktop.png and contact-display-mob.png
My cpanel hosting provider block name which contain words like contact or register.
So I renamed that file and it is working perfectly.
At times this error occurs when you name you folder or files a reserved or blocked name.
In my case I named a folder contact, turns out the name was blocked from being used as folder names.
When testing my script on postman, I was getting this error:
<script>
document.cookie = "humans_21909=1"; document.location.reload(true)
</script>
I changed the folder name from contact to contacts and it worked. The error was gone.
I had the same issue, I was hosting on bigrock.in.
In my case, the issue that my hosting provider said was the user's IP was blacklisted.
You can do a blacklist IP check from here https://mxtoolbox.com
I ran into the same issue as mentioned above. In my situation I was hosting a website on bluehost, which used contact.php to send an e-mail according to the contact-form on the website.
My contact form looked like this:
<div class="col-md-7 contact-form wow animated fadeInLeft">
<form id="contact-form" role="form" onsubmit="formSubmit(event)">
<div class="input-field">
<input id="name" type="text" required name="name" class="form-control" placeholder="Your Name...">
</div>
<div class="input-field">
<input id="email" type="email" required name="email" class="form-control" placeholder="Your Email...">
</div>
<div class="input-field">
<input type="text" name="subject" class="form-control" placeholder="Subject...">
</div>
<div class="input-field">
<textarea id="message" name="message" class="form-control" placeholder="Messages..."></textarea>
</div>
<button type="submit" id="submit" class="btn btn-blue btn-effect">Send</button>
</form>
<div id="form-success-message" class="form-success-message alert alert-success alert-dismissible" role="alert">
<h4 class="alert-heading">Thank you for contacting us!</h4>
<hr>
<p></p>
<strong>The form was submitted successfully.</strong>
<br>In a few minutes you will receive an e-mail confirming that your question was sent successfully.
<br>Our team will contact you soon!
<br>
<br>In case the confirmation e-mail would not arrive within the next hours, verify that the email is not in your SPAM folder, or please contact us directly (****#******.tech).
<button onclick="document.getElementById('form-success-message').style.display = 'none';" type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close form submitted message"></button>
</div>
<div id="form-no-success-message" class="form-no-success-message alert alert-danger alert-dismissible" role="alert">
<h4 class="alert-heading">Oeps, something went wrong</h4>
<hr>
<p></p>
<strong>The form was not submitted.</strong>
<br>Please try again later, or contact us directly via e-mail (******#******.tech) or via WhatsApp.
<button onclick="document.getElementById('form-success-message').style.display = 'none';" type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close form submitted message"></button>
</div>
</div>
The script on my index.html page looked like this:
<script>
// Function responsible for sending the e-mail via the message contact form.
// At the moment the message contact form is submitted, it tries to fetch a php function
// in case the php function is not working, it will return a response from which the ok is false.
// Otherwise, it should return a possitive ok.
// FYI: function does not return a inscanceof error for now.
//
// In case no errors are thrown, the website will display a form success message
// In case the ok response from the php form is negative, a form no success message is displayed.
function formSubmit(event) {
/* Prevent button causing default browser submit */
event.preventDefault();
/* Get form element */
const form = document.getElementById('contact-form');
/* Create form data object from form element which contains post data */
let formData = new FormData(form);
/* Issue "ajax request" to server. Change /post-to-url to the appropriate
url on your server */
fetch('/contact.php', {
body: formData,
method: "post"
})
.then(function(response) {
if(!response.ok){
document.getElementById('form-no-success-message').style.display = 'block';
document.getElementById('contact-form').reset();
}else{
document.getElementById('form-success-message').style.display = 'block';
document.getElementById('contact-form').reset();
}
})
.catch(function(error) {
console.log('Error', error);
});
}
</script>
The file contact.php looked like this:
<?php
if(!isset($_POST['submit']))
{
//This page should not be accessed directly. Need to submit the form.
echo "error; you need to submit the form!";
}
//setting the variables
$name = $_POST['name'];
$visitor_email = $_POST['email'];
$message = $_POST['message'];
//Validate first
if(empty($name)||empty($visitor_email))
{
echo "Name and email are mandatory!";
exit;
}
if(IsInjected($visitor_email))
{
echo "Bad email value!";
exit;
}
//variables for the e-mail to client
$email_from = '***#******.tech';//<== update the email address
$email_subject = "New message via your website contact form";
$email_body = "You have received a new message from the following website visitor (name): $name.\n\nThe visitor used the e-mail address: $visitor_email\n\nThe content of the message is: \n\n $message.";
//variables for the confirmation e-mail to website user
$confirmation_email_subject = "We received your question!";
$confirmation_email_body = "We have received the following message from you via our contact form on our website *****.tech: \n\n Your name: $name.\n\n Your e-mail: $visitor_email\n\n Your message: \n\n $message. \n\nWe will get in contact as soon as possible! If you would not receive an answer in the coming 2 weeks, don't hesitate to contact us via:*****#*****.tech. \n\n This is an automated e-mail. We haven't read your question yet. This is merely a confirmation of the recieval.";
//e-mail of client
$to = "****#*******.tech";//<== update the email address
$headers = "From: $email_from \r\n";
//headers for confirmation
$confirmation_headers = "From: *****#******.tech"; //<== update the email address
//Send the email!
mail($to,$email_subject,$email_body,$headers);
mail($visitor_email,$confirmation_email_subject,$confirmation_email_body,$confirmation_headers);
// Function to validate against any email injection attempts
function IsInjected($str)
{
$injections = array('(\n+)',
'(\r+)',
'(\t+)',
'(%0A+)',
'(%0D+)',
'(%08+)',
'(%09+)'
);
$inject = join('|', $injections);
$inject = "/$inject/i";
if(preg_match($inject,$str))
{
return true;
}
else
{
return false;
}
}
?>
After hosting on bluehost, things worked for 5 minutes. Then I started receiving errors. More specifically, on submitting the form, I received a 409 error, containing:
<script>document.cookie = "humans_21909=1"; document.location.reload(true)</script>
I did some research, and found this page: https://www.geminigeeks.com/bluehost-blocking-contact-form-7-submissions-409-conflict-error/
At the bottom of the page you will read:
This issue still exists. If visitor’s IP is blacklisted, URL with the word “contact” will give 409 error. The plugin author of Contact Form 7 could solve the issue by renaming folders/files and any API calls, from “contact” to “kontact”.
So I changed the PHP file to kontact.php.
And then changed in my script the reference:
<script>
// Function responsible for sending the e-mail via the message contact form.
// At the moment the message contact form is submitted, it tries to fetch a php function
// in case the php function is not working, it will return a response from which the ok is false.
// Otherwise, it should return a possitive ok.
// FYI: function does not return a inscanceof error for now.
//
// In case no errors are thrown, the website will display a form success message
// In case the ok response from the php form is negative, a form no success message is displayed.
function formSubmit(event) {
/* Prevent button causing default browser submit */
event.preventDefault();
/* Get form element */
const form = document.getElementById('contact-form');
/* Create form data object from form element which contains post data */
let formData = new FormData(form);
/* Issue "ajax request" to server. Change /post-to-url to the appropriate
url on your server */
fetch('/kontact.php', { *<===== changes here*
body: formData,
method: "post"
})
.then(function(response) {
if(!response.ok){
document.getElementById('form-no-success-message').style.display = 'block';
document.getElementById('contact-form').reset();
}else{
document.getElementById('form-success-message').style.display = 'block';
document.getElementById('contact-form').reset();
}
})
.catch(function(error) {
console.log('Error', error);
});
}
</script>
After that my contact form started working on bluehost.
I also got the same error, I was getting error code 409 conflicts and an error message :
<script> document.cookie = "humans_21909=1"; document.location.reload(true) </script>
So in my case issue was because my API name is register.php and it was giving an error on mac os, not on windows. So I renamed the API regsiter.php to registerApi.php and it solved the issue.
If you are also using any reserved name for your API name or any method try changing it. Hope it will help.

Meteor, how to submit an array of forms

I have a Meteor application where I want to describe a "site" and a number of "ios" (input/outputs) for each site. The site is described by the first 3 fields and stored in a collection named sites. The ios are entered below that, and are stored in a collection named ios. The idea is each site may have an arbitrary number of ios. I would like to be able to edit any field for the site or any of the ios, click save, and have everything saved at once. Because the number of ios will be limited to say 5 or so by physical circumstances, I think this will be a better user experience than having a separate edit page for ios. However, I can't figure out how to save the ios when the site form is saved. How could this be implemented?
Here is an image of what the form looks like:
https://app.box.com/s/rqjj9lb49twcitwo7rmdy6k9ta0vuztv
Assuming a structure like this:
<template name="form">
<form name="form">
<input type="text" name="foo" />
<input type="text" name="bar" />
<button type="submit">Submit Form</button>
</form>
</template>
Some code like this will add your different elements to different collections:
Template.form.events({
'submit form[name="form"]': function(e) {
var foo, bar, fooInsert, barInsert;
e.preventDefault();
foo = $(e.target).find('[name="foo"]').val();
bar = $(e.target).find('[name="bar"]').val();
fooInsert = {
thing: foo
}
barInsert = {
thing: bar
}
fooInsert._id = Collection1.insert(fooInsert); // Insert foo into Collection1
barInsert._id = Collection2.insert(barInsert); // Insert bar into a different collection, Collection2
}
});
It would help if you did show some code you're working with so we can make our answers better :)

How to add Search with Meteor and Bootstrap?

I am trying to implement searching in my Meteor app. I don't exactly understand how it ties together. At this point, I have this following code:
html:
<form class="navbar-search pull-left">
<input type="text" class="search-query" placeholder="Search">
</form>
js:
Template.menubar.events({
'keyup input.search-query': function (evt) {
console.log("Keyup value: " + evt.which);
if (evt.which === 13) {
console.log("Got an Enter keyup");
Session.set("searchQuery", "justATestVar");
}
}
});
I can see the values of keyup as I press different keys into the search box, so I know the event is being hit. Capturing the "enter" keyup also works, but pressing enter causes the enter site to reload and when I do:
Session.get("searchQuery")
it returns undefined.
I don't know if I'm handling this properly. Essentially, I just want to get the value from the search box and then use that value for making a search on my collection. Any help would be appreciated! Thank you.
You should really use a submit button for your search form to avoid ruining accessibility.
Using a submit button will also enable by default the behavior you're looking for : form submission on enter key pressed.
If you really want to get rid of the submit button, keep it in the DOM but use CSS to hide it.
It's very important to call preventDefault on the event you'll receive from "submit form" handler, if you forget to do so, the page will refresh ruining the meteor "Single Page App" experience (and by the way, page refresh will clear your Session variables, which is why you get an undefined value in the first place).
"submit form":function(event,template){
event.preventDefault();
Session.set("searchQuery",template.find(".search-query").value);
}
What is probably happening is your form is being submitted when you hit enter. Try an preventDefault(). Probably something like this would work:
Template.menubar.events({
'keyup input.search-query': function (evt) {
console.log("Keyup value: " + evt.which);
if (evt.which === 13) {
console.log("Got an Enter keyup");
Session.set("searchQuery", "justATestVar");
}
},
'submit form': function (evt) {
evt.preventDefault();
}
...
You could also try adding evt.preventDefault(); in your keyup but I think it's the form submission that's doing it.
In case anyone got here trying to implement the search function as well, I recommend the following:
meteor add matteodem:easy-search
On client and server:
Players = new Meteor.Collection('players');
// name is the field of the documents to search over
Players.initEasySearch('name');
On the client, make a template.html:
<template name="searchBox">
{{> esInput index="players" placeholder="Search..." }}
<ul>
{{#esEach index="players"}}
<li>Name of the player: {{name}}</li>
{{/esEach}}
</ul>
</template>
Reference

Resources