Need e.preventDefault to save JWT into localStorage - ajax

For some reason, when trying to login I need to have e.preventDefault (prevent page reloading) in order to save my JWT into local storage with an AJAX call. So when i have this:
handleLogin(e) {
//Without e.preventDefault, the jwt token is not save -> cannot access api
e.preventDefault();
const email = $('#email').val()
const password = $('#password').val()
const request = {"auth": {
"email": email,
"password": password
}}
$.ajax({
url: "http://localhost:5000/api/user_token",
type: "POST",
data: request,
dataType: "json",
success: function (result){
console.log(result.jwt)
localStorage.setItem("jwt", result.jwt)
}
})
}
Here is my simple form
render(){
return(
<div>
<form>
<input
name="email"
id="email"
type="email"
/>
<input
name="password"
id="password"
type="password"
/>
<button
onClick={this.handleLogin}
>Login</button>
<button
onClick={this.handleLogout}
>Logout</button>
</form>
<button onClick={this.getUsers}>Get Users</button>
{
this.state.users
}
</div>
)
}
I want my page to reload/go to a different page after submitting a successful login. On create-react-app and using a Rails API 5

In your case, you can try this:
success: function (result){
console.log(result.jwt)
localStorage.setItem("jwt", result.jwt)
//page reload
window.location.reload(true);
// or route to another page
window.location.href = 'foo'; // any route
}
But I would recommend to use react router so your app will never loose it's state.
If you have any query, you can ask.

Related

Success function not being called after making AJAX request codeigniter

When I make an AJAX call from view and pass form data to the controller. I get a couple of problems. First, the code inside success is never executed, and second, the page is being refreshed even though it is an AJAX call. Can anyone tell me where am I doing wrong?
I have seen a lot of questions since yesterday but none of them were able to solve my problem.
Model code
public function insert_user($name, $email) {
$data = array();
$data['name'] = $name;
$data['email'] = $email;
$data['created_at'] = date('y-m-d');
$this->db->insert('all_users', $data);
return true;
}
Controller code
public function insert_user () {
$data = $this->input->post();
$name = $data['name'];
$email = $data['email'];
$this->User_model->insert_user($name, $email);
$this->load->view('view');
}
Ajax request code
const insertBtn = $(".insert-btn");
insertBtn.on("click", function () {
const name = $(".insert-form input[type=name]");
const email = $(".insert-form input[type=email]");
$.ajax({
url: "<?php echo base_url() ?>index.php/Users/insert_user",
type: "post",
data: {name, email},
dataType: "json",
success: function () {
$("body").append("Request made successfully");
}
})
});
My form looks something like this:
<form class="insert-form" action="<?php echo base_url() ?>index.php/Users/insert_user" method="post">
<input type="text" name="name" placeholder="Enter name">
<input type="email" name="email" placeholder="Enter email">
<button class="insert-btn">Insert Data</button>
</form>
NOTE: I am able to successfully insert data into the database.
The browser is submitting the form before your AJAX code gets a chance to run/finish.
Instead of binding an event to the click event of the button, you want to bind to the submit event of the form. Then you want to cancel the browser's default action. This is done via the e.preventDefault(); method.
Also, dataType: "json" is not needed here. dataType tells jQuery what kind of data your AJAX call is returning. You generally don't need it as jQuery can automatically detect it. Plus, if you are not returning a JSON document, then this may cause a problem.
const insertForm = $(".insert-form");
insertForm.on("submit", function (e) {
const name = insertForm.find("input[type=name]");
const email = insertForm.find("input[type=email]");
e.preventDefault();
$.ajax({
url: "<?php echo base_url() ?>index.php/Users/insert_user",
type: "post",
data: {name, email},
success: function () {
$("body").append("Request made successfully");
}
})
});
Controller code
public function insert_user () {
$data = $this->input->post();
$name = $data['name'];
$email = $data['email'];
$data = $this->User_model->insert_user($name, $email);
$this->output
->set_content_type('application/json')
->set_output(json_encode($data));
}
Ajax request code
const insertBtn = $(".insert-btn");
insertBtn.on("click", function () {
const name = $(".insert-form input[type=name]");
const email = $(".insert-form input[type=email]");
$.ajax({
url: "<?php echo base_url() ?>Users/insert_user", // <?php echo base_url() ?>controller_name/function_name
type: "post",
data: {name, email},
dataType: "json",
success: function () {
$("body").append("Request made successfully");
}
})
});
form looks something like this:
<form class="insert-form" method="post">
<input type="text" name="name" placeholder="Enter name">
<input type="email" name="email" placeholder="Enter email">
<button class="insert-btn">Insert Data</button>
</form>
The page was being refreshed because I had a button that was acting as submit button on changing it to the input of the type button it does not submits the form and we don't see the page being refreshed. And also the AJAX request made also runs successfully.
<form class="insert-form" action="<?php echo base_url() ?>index.php/Users/insert_user" method="post">
<input type="text" name="name" placeholder="Enter name">
<input type="email" name="email" placeholder="Enter email">
<input type="button" class="insert-btn" value="Insert Data">
</form>

Ajax call is being accidently triggered

I'm creating a login page and at the bottom of the pop-up form, there is another button that takes you to the registration page. The issue appears to be that when navigating to the new page it all sits under the original sign-in form which uses an ajax call to check if the user exists so when they try to submit the registration form it then calls that ajax call from the sign-in form.
Sign-in form
<div id="myForm">
<form onsubmit="return false;" id="loginForm">
<h1>Login</h1>
<label for="email"><b>Email</b></label>
<input type="email" id="email" placeholder="Enter Email" name="email" required>
<label for="psw"><b>Password</b></label>
<input type="password" id="psw" placeholder="Enter Password" name="psw" required>
<div id="message" class="alert-danger"></div>
<br />
<button type="submit" id="submit" class="btn">Login</button>
<button type="button" class="btn cancel" onclick="closeForm();">Close</button>
</form>
<div class="d-inline">
<button class="btn-info">#Html.ActionLink("User Registration", "SignUp", "SignUp_SignIn")</button>
</div>
</div>
Then the ajax call is
$(document).ready(function () {
$("form").on('submit', function (event) {
var data = {
'email': $("#email").val(),
'psw': $("#psw").val()
};
$.ajax({
type: "POST",
url: 'SignUp_SignIn/CredentialCheck',
data: data,
success: function (result) {
if (result == true) {
$("#message").text("Login attempt was successful");
}
else {
$("#message").text("Email/Password didn't match any results");
}
},
error: function () {
alert("It failed");
}
});
return false;
});
});
After looking at the comments I realized that the reason that the login form was being called from the layout.cshtml so when the ajax call was being called it was grabbing all the form tags that existed on any page that was loaded up. After changing the ajax so it was calling a specific id for the login form instead of form it allowed for proper actions to take place.
An example of what I'm refusing to
$(document).ready(function () {
$("form").on('submit', function (event) {
$.ajax({
type: "POST",
url: url,
data: data,
success: function (result) {
//Do stuff
}
});
});
});
The above will try to redirect you on the submit of any form that is loaded up, but if we go through and change the way it accesses the form like below then it will only work if the one specific form is submitted.
$(document).ready(function () {
$("#loginForm").on('submit', function (event) {
$.ajax({
type: "POST",
url: url,
data: data,
success: function (result) {
//Do stuff
}
});
});
});

AJAX is not submiting data to php

I have a form which collects some data that data is then stored into local variables, which all worked fine. I then decided that i also wanted to send this data to a php page on the server.
However when I added the AJAX code everything stops and nothing happens, this is built for an app using cordova and i can't seem to debug it.
window.onload = function()
{
document.addEventListener("deviceready", init, false);
}
function init()
{
document.getElementById("btnSave").addEventListener("click",saveData, false);
document.getElementById("btnGet").addEventListener("click", getData, false);
}
function saveData()
{
var user = document.getElementById("user").value;
var name = document.getElementById("name").value;
window.localStorage.setItem("user", user);
window.localStorage.setItem("name", name);
var deviceID = device.uuid;
window.localStorage.setItem("uuid", deviceID);
$.ajax({
type: "POST",
url: "http://www.mydomain.co.uk/folder/add.php",
data: {
user : user,
name : name,
},
success: function(response){
alert("Thank you your information has been saved");
}
});
}
And the form
<label>Username:</label>
<input name="user" type="text" placeholder="" id="user" class="stored form-control">
<label>Name:</label>
<input name="name" type="text" placeholder="" id="name" class="stored form-control">
<button id="btnSave">Save Data</button><br />

Express.js multer don't see text fields only file

When i use AJAX request to send multipart/form-data form to server containing picture and 3 text fields, multer process only image, but no text-fields. How to extract text fields from there?
FormData constructor
handleSubmit = () => {
let formData = new FormData(this.refs.productSubmit);
this.props.submitProduct(formData);
}
Form
<form action="javascript:void(0);" onSubmit={this.handleSubmit} ref="productSubmit">
<label> Название </label>
<input className={'form-control'} type="text" name="name" />
<label> Цена </label>
<input className={'form-control'} type="text" name="price" />
<label> Описание </label>
<input className={'form-control'} type="text" name="description" />
<label> Изображение </label>
<input className={'form-control'} type="file" name="picture" style={{height: '100%'}}/>
<hr/>
<button className={'btn btn-warning btn-lg'} bsSize={'small'} type="submit"> Добавить </button>
</form>
Async action creator with AJAX call inside
export function submitProduct(formData) {
return function(dispatch) {
return (
$.ajax({
url: '/addproduct',
method: 'post',
cache: false,
contentType: false,
processData: false,
data: formData,
success: data => {
//dispatch(addedProduct());
},
error: (xhr, status, err) => {
console.error(this.props.url, status, err.toString());
}
})
);
};
}
Server-side request processer
app.post('/addproduct', isLoggedIn, isAdmin, upload.single('image'), (req, res) => {
console.log(req);
console.log(req.body);
console.log(req.file);
});
But req.body is undefined. File is accessable. Fields ARE present in payload request, i can see them with firefox devtools.How to get thoose text fields?
Since Express 4.0 you need to manually add the body-parser middleware, otherwise forms don't get parsed and req.body will be undefined.
In your main file, you should do something like this:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// ...
module.exports = app;

How to include CSRF from Codeigniter into ajax data

I am trying to pass some data into my Controller, but I'm getting a 500 error. After some research, I discovered that it's caused by the CSRF token not being sent.
It seems like I need to include this along with the data: <?php echo $this->security->get_csrf_token_name(); ?>:"<?php echo $this->security->get_csrf_hash(); ?>"
My JS is pretty weak, so I'm a little confused on how to alter this to include the above.
<script type="text/javascript">
$(document).ready(function() {
$("#order").sortable({
update : function (event, ui) {
order = $('#order').sortable('serialize');
$.ajax({
url: "<?=base_url().'admin/category/update_order'?>",
type: "POST",
data: order,
success: function(response){
console.log(response);
}
});
}
});
}
);
</script>
The token needs to be passed in the data argument of $.ajax.
This should work but see my notes below.
order['<?php echo $this->security->get_csrf_token_name(); ?>'] = '<?php echo $this->security->get_csrf_hash(); ?>';
However, there are a few bad practices going on here. Mainly you should not use PHP in your javascript because this prevents you from being able to access the javascript as a separate file (this is good because browsers will cache it to make your page load faster and consume less bandwidth).
It's better to store the token in your order <form> html like this..
<input type="hidden" name="<?php echo $this->security->get_csrf_token_name(); ?>" value="<?php echo $this->security->get_csrf_hash(); ?>" />
Then it will get serialized with the rest of your form data.
You can also store the URL in the form's action attribute. This will help your script gracefully degrade and also keeps the URL in one place instead of 2.
<form id="order" method="post" action="<?=base_url()?>admin/category/update_order">
In the $.ajax call, use something like this url: $('#order').attr('action'), assuming #order is the actual form id.
CI stores csrf in cookie and you can fetch it from there:
var csrf = $.cookie('csrf_cookie_name');
The downside of this method is that jQuery doesn't natively provide cookie access. So you will need a jquery plugin.
You're correct, just add the CSRF token to your post data. You can use jQuery's $.extend function to merge your order object you already created with the CSRF token data, like this:
$.extend(alerts, {
'<?php echo $this->security->get_csrf_token_name(); ?>' :
'<?php echo $this->security->get_csrf_hash(); ?>' });
Here's a different approach. Simple function in Auth.php that returns the csrf token name and hash in JSON format. Then, in our javascript, make two ajax calls, the first to grab the csrf creds and insert them into hidden form fields, the second to handle our actual form submit.
// place function in Auth.php controller
public function get_csrf()
{
$csrf['csrf_name'] = $this->security->get_csrf_token_name();
$csrf['csrf_token'] = $this->security->get_csrf_hash();
echo json_encode($csrf);
}
// myFunction()
<script type="text/javascript">
function myFunction() {
// first ajax call to grab the csrf name and token
// from our get_csrf() function in Auth.php
$.ajax({
type: "GET",
dataType: 'json',
url: "https://<your_domain>.com/auth/get_csrf", //replace with your domain
success: function (data) {
// assign csrf name and token to variables
csrf_name = data.csrf_name;
csrf_token = data.csrf_token;
// assign field1 and field2 field values to variables
var form_field1 = document.getElementById('field1').value;
var form_field2 = document.getElementById('field2').value;
// insert csrf creds into form
$('#csrftoken').attr('name', csrf_name);
$('#csrftoken').val(csrf_token);
// second ajax call -- this is our form handler
$.ajax({
type: "POST",
url: "https://<your_domain>.com/<your_controller>/<your_function>", //replace with your domain/controller/function
data: {
// ES6 computed property keys are great...
[csrf_name] : csrf_token,
"field1" : form_field1,
"field2" : form_field2
},
success: function(data) {
// handle the return from your form submit
if (data == "ok") {
console.log("Success!");
$("#infoMessage").html("<p>Success</p>").fadeIn(300);
} else {
console.log("Oops!");
$("#infoMessage").html("<p>Oops!</p>");
}
}
});
}
});
}
</script>
// html
<div id="infoMessage"></div>
<form method="post" accept-charset="utf-8">
<input type="hidden" id="csrftoken" name="" value="" />
<label for="field1">Field 1:</label> <br />
<input type="text" name="field1" id="field1" />
<label for="field2">Field 2:</label> <br />
<input type="text" name="field2" id="field2" />
<input type="button" name="submit" value="SUBMIT" onclick="myFunction()" />
</form>
I extend form_helper as MY_form_helper.php to serve csrf tokens to my own form generation code - you could use something similar:
function secure_form() {
$CI =& get_instance();
return '<input type="hidden" name='.$CI->security->get_csrf_token_name().' value='.$CI->security->get_csrf_hash().'>';
}
another solution is to use .serialize():
$.post("user/save", $('#frmUser').serialize(),function(html){
$("#results").html(html);
});
that will find the hidden field that stores the CSRF data.

Resources