Jump to content

Forget password form not working with Ajax


B_CooperA
Go to solution Solved by Psycho,

Recommended Posts

I've made a form with CodeIgniter to retrieve users password and send it to the given email address. However, if I'm trying to send the request with Ajax, it doesn't work. It is working without the Ajax part.

 

Form:

 

<form action="<?=base_url()?>users/forgot_pass" method="post" id="forget_pass_form">






<div class="form_header">

<h1>Unohditko salasanasi?</h1>

</div>

<p>Tilaa uusi salasana syöttämällä sähköpostiosoitteesi</p>

<div class="front_success" style="display:none" id="forgot-pass-success">


<p>Salasana on lähetetty antamaasi sähköpostiosoitteeseen.</p>


</div>

<div class="login_error" style="display:none" id="forgot-pass-error">


<p>Sähköpostiosoitetta ei löytynyt järjestelmästämme.</p>


</div>

<div id="loading_spinner"></div>


<p><input type="text" name="to_email" placeholder="Sähköpostiosoite" class="user" style="background-postion: -200px; margin-top: 20px;" />


<input type="submit" name="to_submit" value="Lähetä salasana" class="login_submit" id="forget-pass" /></p>


</form>

Here's the controller to handle the form:

 

<?php


class Users extends CI_Controller {

public function forgot_pass() {


if($_POST['to_submit']) {


$this->load->model('user');


$email = $_POST['to_email'];


$email_addr = $this->user->get_email_address($email);


if(!empty($email_addr)) {


foreach($email_addr as $row) {


$this->load->library('email');


$this->email->from('your@example.com', 'Your Name');
$this->email->to($email);  
$this->email->subject('Password');
$this->email->message($row['password']); 


if($this->email->send()) {

echo "1";

} else {

echo "0";
}


}
}

}

} 

}

?>

And here's the JS file:

 

$(document).ready(function() {

$("form#forget_pass_form").on('submit', function(){


var from = $(this);

$.ajax({

         url: from.attr('action'),
         type: from.attr('method'),
         data:$(from).serialize(),
         beforeSend: function(){


                         $("#loading_spinner").show();

                 },
         success: function (data) {

               if(data == '1'){
    //if the email is send then it return 1 so that you show success msg


               $(".front_success").show();
                 } else {
   //if the email is not send then it return 0 so that you show error msg


               $("#forgot-pass-error").show();
               }
        $("#loading_spinner").hide();// hide when ajax complete


              }
     });
     return false;

     });

}); 
Each and everytime it will show that "login_error" div even though I have typed my email address correctly. Any help would be appreciated
 
Link to comment
Share on other sites

 

I've made a form with CodeIgniter to retrieve users password and send it to the given email address. 

 

Forget your AJAX problem. You first need to resolve the issue that you are apparently storing an unhashed value for the user's password. No one, not even you, should have access to the user's password. You should store a hash of the user's password which is a sort of one-way encryption. If done correctly, it would be impossible to ever revert the hashed value back to the original value provided by the user. And, you're sending this through email no less!

Edited by Psycho
Link to comment
Share on other sites

I already know this. I'm just making some simple tests and of course the final product will be nothing like this. I'd be more than happy if anyone is able to help me.

If you know that then why are you not implementing a password reset process instead of going to the trouble of retrieving their current password to send to them? If you truly intend to do it correctly, then why are you wasting time writing code to do something the wrong way? It would make more sense if you were just building this to send a mock email with the intent of updating it to send a new temp password rather than writing code to retrieve the password.

 

As to your problem, what debugging have you done so far and what did you find? We can't solve your problem since we don't know what the results are. So, pick one place of possible failure and verify what is or is not happening. Here is the break-down as I see it should go:

1. The JavaScript makes a call to a PHP page passing the email value

2. The PHP page takes the email value, performs operations and returns a 1 or 0

3. The JavaScript page takes the return value to determine what to show/hide

 

All you know is that in step 3 you are always getting the error condition, I would start by testing the PHP page by directly submitting the form instead of calling it via AJAX. If that works then adding some debugging to the PHP page to verify the data it is receiving from the AJAX call the ultimate output. However, since this is being called via AJAX you need a way to output that info. You could either have the page write debugging info to a flat file that you inspect or you could output the debugging info back to the AJAX return function and output it to the page.

 

 

Edit: After reading the PHP file, all it contains is a class. Is that the file that is called from the AJAX request? If so, the class is never instantiated or called. So, that page would simply return nothing. Also, that function has almost zero error handling. Plus, the logic in it isn't making sense to me. For example, why is there a foreach() loop on something that should only include a single record?

 

Anyway, you just need to follow some simple debugging processes. Take one point in the process and add some debugging code to verify the data coming in and the data going out.

 

- If the data coming in is not right, then you know that the problem exists somewhere earlier in the process

- If the data coming in is correct, but incorrect going out - then you've found at least one problem and can address it

- If the data coming in and going out is correct, then you know the problem exists somewhere later in the process.

Link to comment
Share on other sites

As to your problem, what debugging have you done so far and what did you find? We can't solve your problem since we don't know what the results are. So, pick one place of possible failure and verify what is or is not happening. Here is the break-down as I see it should go:

1. The JavaScript makes a call to a PHP page passing the email value

2. The PHP page takes the email value, performs operations and returns a 1 or 0

3. The JavaScript page takes the return value to determine what to show/hide

 

 

Well, the script works perfectly without the ajax. So the PHP file itself is working properly. 

 

Edit: After reading the PHP file, all it contains is a class. Is that the file that is called from the AJAX request? If so, the class is never instantiated or called. So, that page would simply return nothing.

 

 

The method forgot_pass() is called from the AJAX request.. And since I'm using CodeIgniter (MVC pattern), why should I instantiate the class? 

 

 For example, why is there a foreach() loop on something that should only include a single record?

 

 

Yeah I know foreach() loop isn't the most fanciest way to loop if there are only record one. I could of use while() loop instead

Link to comment
Share on other sites

Well, the script works perfectly without the ajax. So the PHP file itself is working properly. 

OK, good. That's the type of information that would be helpful to know up front.

 

The method forgot_pass() is called from the AJAX request.. And since I'm using CodeIgniter (MVC pattern), why should I instantiate the class? 

Well, I don't see how that class gets called from the AJAX request. It may not be getting used at all for all I know. You could do a couple of quick tests to see what is happening.
Change the success condition in the AJAX call to alert() the returned value. Then you can verify what, if anything, is being returned. If you do get a 0 response then change the PHP method to return the $_POST['to_email'] value (with the alert still in place) so you can verify the AJAX is passing the value correctly. If you aren't getting anything inthe alert() then that method is not getting called.
 

Yeah I know foreach() loop isn't the most fanciest way to loop if there are only record one. I could of use while() loop instead

What I meant was why do you have a loop at all? IF there will only be one record just reference that record directly

 

if(!empty($email_addr))
{
    $this->load->library('email');
    $this->email->from('your@example.com', 'Your Name');
    $this->email->to($email);  
    $this->email->subject('Password');
   $this->email->message($email_addr[0]['password']); // <<==
Link to comment
Share on other sites

 

Well, I don't see how that class gets called from the AJAX request. It may not be getting used at all for all I know. You could do a couple of quick tests to see what is happening.

Change the success condition in the AJAX call to alert() the returned value. Then you can verify what, if anything, is being returned. If you do get a 0 response then change the PHP method to return the $_POST['to_email'] value (with the alert still in place) so you can verify the AJAX is passing the value correctly. If you aren't getting anything inthe alert() then that method is not getting called.

 

Well, yeah, I got an empty alert().

 

I thought ajax would grab the method in here:

url: from.attr('action')

So the question is how do I call that method so that ajax can get the value from that forgot_pass() method?

Link to comment
Share on other sites

You stated that the page works when you do not implement the AJAX call and just let the form post to the PHP page identified in the action parameter, correct? That doesn't make sense since it would just load the page with the class definition, but not actually use the class. If you are not getting a response from the AJAX call, the first order of business is to verify that it is even calling the page correctly.

 

You are setting the URL for the AJAX call using this

 

url: from.attr('action'),

 

You should validate that it is the value you think it is. Try adding a line right after you define from

 

var from = $(this);
alert(from.attr('action'));

 

If that isn't alerting the value you expect then that's the source of your problem. If it is the value you expect, then go to the next logical step in the process and verify the data.

Link to comment
Share on other sites

You should validate that it is the value you think it is. Try adding a line right after you define from

 

var from = $(this);

alert(from.attr('action'));

 

If that isn't alerting the value you expect then that's the source of your problem. If it is the value you expect, then go to the next logical step in the process and verify the data.

 

 

I alerted the form action, and yes it was directing into that forgot_pass method.. Could it be that the error is caused by that login method? Every time I submit the button and take a look at developer tools tab, the referer line is always indicating to that login method? Am I loading the views wrong?

 

Here's my whole controller:

<?php

	class Users extends CI_Controller {


	
	public function login() {

		$data['error'] = 0;
				
		if(isset($_POST['submit'])) {

		        $this->load->model('user');		
					
		        $email = $_POST['email'];	
			$password = $_POST['password'];	

						

			$user = $this->user->login($email, $password);	
					

				if(!$user) {

				$data['error'] = 1;		
					

				} else {

				echo "Kirjautuminen onnistui";
		
				}

			}

			$this->load->view('header');
			$this->load->view('index', $data);
			$this->load->view('footer');

		}
			


		public function forgot_pass() {

			
			if(isset($_POST['to_submit'])) {

				$this->load->model('user');

				$email = $_POST['to_email'];

				$email_addr = $this->user->get_email_address($email);

				        if($email_addr) {

					$this->load->library('email');

				$this->email->from('your@example.com', 'Your Name');
				$this->email->to($email);  
				$this->email->subject('Test');
				$this->email->message($email_addr[0]['password']);	

					if($this->email->send()) {
									
						echo "1";

					} else {

						echo "0";
					}
				}
			}

			$this->view->load('header');
			$this->view->load('index');
			$this->view->load('footer');
		}


	}
?>
Link to comment
Share on other sites

 

I alerted the form action, and yes it was directing into that forgot_pass method.. Could it be that the error is caused by that login method? Every time I submit the button and take a look at developer tools tab, the referer line is always indicating to that login method? Am I loading the views wrong?

 

What you are stating makes no sense. You can't have the AJAX call a method. An AJAX call has to be to a PHP page that will be processed just as if the user typed the URL into their browser. The AJAX call doesn't automatically initiate/run a method on the page called. So, either you are doing something completely wrong or you are using the wrong terminology which is making it difficult to help you.

 

You stated previously that the functionality worked when you let the form post normally (w/o the AJAX). If your form action is pointing to the file where the Users class is defined, then I call BS. Just loading that script would do nothing. All it does is define the class - it never calls the class to actually do anything.

Link to comment
Share on other sites

So the only option is to put that method in separate file?

 

That's not what I was saying at all. You are making this difficult to try and help you because there is some miscommunication here which I believe is due to the misuse of the wrong terminology. Also, I explained the process to try and debug the problem yourself, but I've not seen that you actually attempted that process in any meaningful way. I still haven't seen a single piece of code that ever instantiates the Users class or calls the forgot_pass() method. The fact that your alert was empty shows that the method is never getting called OR it is going into one of the conditions that has no output - because the method is poorly written. You could at least change your method so it would always have an output.

class Users extends CI_Controller
{
    public function forgot_pass()
    {
        if(!$_POST['to_submit'])
        {
            exit("No post value");
        }
 
        $this->load->model('user');
        $email = $_POST['to_email'];
        $email_addr = $this->user->get_email_address($email);
        if(empty($email_addr))
        {
            exit("Email address not found");
        }
 
        $password = $email_addr[0]['password'];
        $this->load->library('email');
        $this->email->from('your@example.com', 'Your Name');
        $this->email->to($email);  
        $this->email->subject('Password');
        $this->email->message($password); 
 
        echo ($this->email->send()) ? 1 : 0;
    } 
}

 

If you still do not see anything int he alert then you know the method is not being called - which is what I believe is happening.

Link to comment
Share on other sites

Okay, I did what you posted above, copied your version of the method. And now I'm getting "No post value" as output and a notice of undefined index of "to_submit". So it doesn't recognize the form is being submitted. So how should I pull this off?

Link to comment
Share on other sites

OK, so what IS in the POST data? I'm doing my best to help you, but I feel I have to spoon feed you everything. I am not very strong in AJAX, plus these types of problems can be difficult to debug since the data is crossing multiple technologies. I provided guidance above on how you should approach debugging an issue, but it seems as soon as you find a problem you throw up your hands in despair.

 

So, let's take inventory of where we are at. You can now confirm that the PHP method is being executed. But, it is not receiving the data that it expects. So, the logical question (at least to me) is what data IS being sent? YOU can answer that by adding some more debugging code to that method.

 

Change

 

exit("No post value");

 

To

 

$msg = "No post value<br>";
$msg .= "POST: <pre>" . print_r($_POST, 1) . "</pre>";
exit($msg);

 

Now you will know what is being sent with the AJAX request. I think the problem is in how you are sending the form data

 

data:$(from).serialize(),

 

But, as I said, AJAX is not my strong suite.

Link to comment
Share on other sites

  • Solution

OK, I'm pretty sure I found the issue. I had to construct some working pages using the code you provided above, and the problem is actually pretty simple. You are submitting the page via AJAX! In other words, the user is NOT clicking the submit button. You made the submit button an input field. Input buttons are only passed if they are clicked! I was able to verify this by just doing the simple debugging I proposed above. The return value that was alerted in the java script showed that the to_email was included in the POST data, but that was it.

 

So, this line in the method is always returning false:

if($_POST['to_submit']) {

That's a poor implementation. I see it a lot, but checking to see if a submit button was clicked is not the best way to check if a form is posted. For a form with multiple input fields you can check the $_SERVER super global for the request method. But, in this case, the user in only submitting one field. So, you should just check that.

 

This should resolve your problem

class Users extends CI_Controller
{
    public function forgot_pass()
    {
        if(!$_POST['to_email'])
        {
            //No email post value
            return 0;
        }
 
        $this->load->model('user');
        $email = $_POST['to_email'];
        $email_addr = $this->user->get_email_address($email);
        if(empty($email_addr))
        {
            //Email address not found
            return 0;
        }
 
        $password = $email_addr[0]['password'];
        $this->load->library('email');
        $this->email->from('your@example.com', 'Your Name');
        $this->email->to($email);  
        $this->email->subject('Password');
        $this->email->message($password); 
 
        //Return true false based upon result of send() response
        echo ($this->email->send()) ? 1 : 0;
    } 
}
Edited by Psycho
Link to comment
Share on other sites

Thank you so much! God how stupid I am, so simple mistake yet so crucial.

 

You're welcome. But, the whole point of this exercise (for me) was for you to learn some simple debugging techniques. It's not hard, it just takes a little thought and a little bit of work. First understand the process. Then identify a certain point in the process that may not be working correctly. Add some debugging code to verify what the input data and the output data is from that process. From that you can determine if the problem is before or after that point. Then just move your debugging efforts forward/backward from that point and try again.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.