Issue with ajax call csfr token - ajax

I am trying to add an ajax call that changes the status of a listing, between listed and unlisted, when submitting the form I am having a 403 forbidden error in the console of the browser, I made some checking and it appears that Django is forbidding the form because of a lack of csrf token, however I am not good in javascript, so any help would be appreciated.
Here is my code in my view:
#require_POST
#ajax_required
#login_required
def unlist_ajax(request):
pk = request.POST.get('pk', None)
is_visible = request.POST.get('is_visible', None)
if pk and is_visible:
listing = get_object_or_404(Listing, pk=pk)
if is_visible == 'true':
listing.is_visible = False
listing.save()
messages.success(request, _("Listing unlisted"))
return JsonResponse({'status': 'ok'})
else:
listing.is_visible = True
listing.save()
messages.success(request, _("Listing re-listed"))
return JsonResponse({'status':'ok'})
and here is the template script:
in the top of the template, in the header:
<script>
function unlistPostAjax(listing_id, is_visible) {
var confirmation = confirm("{% trans 'are you sure you want to change the status of your listing?' %}");
if (confirmation) {
$.post("{% url 'dashboard:unlist_ajax' %}", {pk: listing_id, is_visible: is_visible}, function (response) {
console.log('sending delete query'); location.reload();
})
}
}
</script>
and in the bottom of the body:
<script src="{% static 'js/jquery.cookie.js' %}"> </script>
<script>
$(document).ready(function () {
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod (method) {
// These HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if(!csrfSafeMethod(settings.type) && !this.crossDomain) {
// Set X-CSRFToken HTTP Header
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
});
</script>

You can add this to the top of your <script> or if you have a base html template you can put this in there too.
{% csrf_token %}
<script type="text/javascript">
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
</script>
Believe you just need to add the csrf above the script you defined, but this is the whole implementation I currently use. I have no issues.

Related

Using Ajax in laravel and giving me unknown status. Why?

In my application i am using Ajax request but it is giving me jquery-3.3.1.js:9600 POST http://localhost:8000/get_types_ajax
gettin 419 (unknown status)
My javascript is:
$(document).ready(function() {
var ckbox = $("input[name='particulars']");
var chkId = '';
$("input[name='particulars']").on('change', function() {
if (ckbox.is(':checked')) {
values = [];
names = [];
$("input[name='particulars']:checked").each ( function() {
amount = $(this).val().split(",");
console.log("amount",amount);
values.push(amount[0]);
names.push(amount[1]);
});//checked
total_value = 0;
values.forEach(function(value) {
value = Number(value);
total_value = total_value + value;
document.getElementById('total').innerHTML = total_value;
});//foreach
}//if
else {
total_value = 0;
document.getElementById('total').innerHTML = total_value;
}
$.ajax({ url:"{{url('/get_types_ajax')}}",
type: 'POST',
data: {message:names},
success: function (data)
{
console.log(data);
}
});
});//onchange
});//ready
my web.php is :
Route::post('/get_types_ajax', 'DevkrutyaController#get_types');
The 419 error you are getting is due to the missing CSRF token in your ajax request. To pass a csrf token you can use ajax setup method of jquery
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
});
$.ajax({
url:"{{url('/get_types_ajax')}}",
type: 'POST',
data: {message:names},
success: function (data)
{
console.log(data);
}
});
});//onchange
});//ready
For more information https://laravel.com/docs/master/csrf#csrf-x-csrf-token
i see.You don't pass CSRF_TOKEN WITH Post Request
if your are using post method then u must pass CSRF_TOKEN with that other wise you can ignore(skip) some Url in VerifyCSRF token middleware
protected $except = [
'stripe/*',
];
other wise add this line in your js file it will automatically send
csrf token
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
for more detail read this article
Laravel uses CSRF token to protect your application from cross-site request forgery (CSRF) attacks. You will need to pass the CSRF token in your ajax.
In header
<meta name="csrf-token" content="{{ csrf_token() }}" />
In script
<script type="text/javascript">
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
</script>

Redirect to a specific page in Laravel using ajax

I have created ajax function when the user clicks the button, it will check first the users profile if account is already confirmed. If not, it will redirect back to user dashboard. However, my problem now is that the page is not displayed or it is not redirecting back. The result can only be seen in the browsers' network tab.
my ajax
$(document).on("click", "#apply", function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: "get",
url: '/checkstatus',
success: function(store){
if(store == 'confirmed'){
$(".apply_modal").toggleClass("open").show();
$("body").toggleClass("open");
}
},
});
});
and my controller:
public function checkStatus(Request $request)
{
$verify = Auth::user()->verifyAccount();
if($verify == false){
if(session()->has('verify') && session()->get('verify') != '') {
session()->forget('verify');
} else {
session()->flash('verify', 'At first, please update your profile!');
}
}else{
return 'confirmed';
}
}
How can I properly redirect back the user to its main page? The result for now is like this.
Message to the user :
#if(session('verify'))
<div class="complete_box">
<p>{{ session('verify') }}</p>
Close
</div>
#endif
you can not redirect through controller if you are using ajax. you need to use javascript
window.location.href = "your url";
window.location.href = "{{url('/mypage')}}";
$(document).on("click", "#apply", function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: "get",
url: '/checkstatus',
success: function(store){
if(store == 'confirmed'){
$(".apply_modal").toggleClass("open").show();
$("body").toggleClass("open");
window.location.href = "your url";
}
},
});
});
for flash message use session
public function checkStatus(Request $request)
{
$verify = Auth::user()->verifyAccount();
if($verify == false){
\Session::put('message','At first, please update your profile!');
return 'something you want';
}else{
return 'confirmed';
}
}
Now in blade file where you want to show flash put this
#if(Session::has('message'))
<p class="alert alert-success">
{!! Session::get('message') !!}
×
</p>
#endif
$(document).on("click", "#apply", function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: "get",
url: '/checkstatus',
success: function(store){
if(store == 'confirmed'){
$(".apply_modal").toggleClass("open").show();
$("body").toggleClass("open");
window.location.href = "store.url";
}
},
});
});
Here the store.url is that url which is coming in response.
In controller
Craete a url and send in response.

CSRF token mismatch while uploading image using ajax in CakePHP 3.6

I have tried
class UsersController extends AppController
{
public function beforeFilter(Event $event)
{
$this->getEventManager()->off($this->Csrf);
}
public function ajaxEdit($id = null)
{
$this->autoRender = false;
debug($id);
debug($this->request->getData());
}
And I am using ajax code
$(document).ready(function(){
$('#user-profile').change(function(){
$('.loader-body').show();
var form = $('#user-profile-image')[0];
var formData = new FormData(form);
var tutorial_id = $('#user-file-id').val();
$.ajax({
url :"/users/ajax-edit/"+tutorial_id,
method:"POST",
data:formData,
contentType:false,
cache: false,
processData:false,
success:function(data){
let parseData = $.parseJSON(data);
if (parseData.status === true) {
location.reload();
var value = parseData.url;
console.log(value);
} else {
alert(parseData.message);
}
}
});
});
});
I have followed help from these links
CakePHP ajax CSRF token mismatch
2 https://book.cakephp.org/3.0/en/controllers/components/csrf.html
Getting CSRF token mismatch (see attached image)
https://i.stack.imgur.com/FsVZu.png
First of all if your are using POST method in your ajax call then you should send tutorial_id as data instead of sending it in the url.
You can resolve this by sending you CSRF token through a special X-CSRF-Token header in your ajax call.
https://book.cakephp.org/3.0/en/controllers/components/csrf.html
beforeSend: function (xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('[name="_csrfToken"]').val());
},
OR
You can disable CSRF component[Not recommended by the Cakephp] for your ajax action like:
public function beforeFilter(Event $event) {
if (in_array($this->request->action, ['ajaxEdit'])) {
$this->eventManager()->off($this->Csrf);
}
}

Where to find angular-xeditable and ajax together work simple example

Now, I am using angular-xeditable.I want to send edit data to server.
<div ng-controller="Ctrl">
{{ user.name || "empty" }}
</div>
and js code is
<script type="text/javascript">
var app = angular.module("app", ["xeditable"]);
app.controller('Ctrl', function($scope,$http) {
$scope.user = {
name: 'awesome user'
};
$http.post("<?php echo base_url(); ?>index.php/welcome/test", {"name":name})
.success(function(data, status, headers, config) {
$scope.data = data;
})
.error(function(data, status, headers, config) {
$scope.status = status;
});
});
</script>
I received name variable is empty value.
This code doesn't work.I can't find error.
You need to invoke your code that posts to the server on the onaftersave event, which is documented here: http://vitalets.github.io/angular-xeditable/#onaftersave
This event is called after the changes in the inputbox have been set on the model.
In your HTML put the function call in the onaftersave attribute like this:
<div ng-controller="Ctrl">
{{ user.name || "empty" }}
</div>
In your controller create the postName function which actually posts the data to the server. Your code would look like this:
<script type="text/javascript">
var app = angular.module("app", ["xeditable"]);
app.controller('Ctrl', function ($scope, $http) {
$scope.user = {
name: 'awesome user'
};
// Called on the onaftersave event of xeditable
$scope.postName = function () {
$http.post("<?php echo base_url(); ?>index.php/welcome/test", {"name": $scope.user.name})
.success(function (data, status, headers, config) {
$scope.data = data;
})
.error(function (data, status, headers, config) {
$scope.status = status;
});
}
});
</script>

Django Ajax-jQuery

Since I am relatively new to Ajax and jQuery, and having hard time doing this, I am posting this over here.
Views.py
if request.is_ajax():
if request.method == "POST":
chatroom_id = request.POST['chatroom_id']
else:
chatroom_id =''
print chatroom_id
When I remove if request.is_ajax() condition , then it shows the error saying Key 'chatroom_id' not found in <QueryDict: {u'reply': [u''], u'csrfmiddlewaretoken': [u'yIJct9O7WfyPnWmDosW9N5TEklRwoIHP']}>
Template.html
{% for key, values in chat_data.items %}
<div class="container-fluid" alt = {{key}}>
<div class="row-fluid">
<div class="span2">
{{values.from}} <br/> {{values.init_query}}
</div>
<div class="span10 well">
{% for k in values.chat %}
<label> Text : {{k.text}} </label>
<label> {{k.date_time}} </label>
{% endfor %}
<form action = "#" method = "POST" id = {{key}} class="chatroom">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value = "Sent" class="btn btn-primary">
</form>
</div>
</div>
</div>
{% endfor %}
Since, there will be many chats and correspondingly reply submit button and its key, I want that when I reply to a specific chat, it carries the key with itself and process the chat accordingly.
How can I achieve this using Django, jQuery and Ajax? Replies to be being sent should give via Ajax using jquery
I have written these jQuery lines of code, but they seem not to work. Where I am going wrog
<script type="text/javascript">
var form = $('#'+'{{key}}');
form.submit(function (event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "/dashboard",
data : form.serialize(),
success: function( response ) {
console.log( response );
}
});
return false;
});
I believe that the best free resource on the matter is Mike Hibbert's video on using django with jquery to implement ajax.
For the jQuery, you have a few mistakes, the post should look like this:
var form = $('#'+'{{key}}');
form.submit(function (event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "/dashboard",
data : form.serialize(),
success: function( response ) {
console.log( response );
}
});
return false;
});
Try that and tell me how it goes.
When you make an Ajax request with jQuery and Django with csrf you need to pass the token, this uses the jQuery cookie plugin from Django's docs https://raw.github.com/carhartl/jquery-cookie/v1.3.1/jquery.cookie.js :
/** Django's csrftoken ajax security & server failures */
App.ajax = (function () {
var csrftoken = $.cookie('csrftoken'),
host = document.location.host,
protocol = document.location.protocol,
sr_origin = '//' + host,
origin = protocol + sr_origin;
return {
'csrfSafeMethod': function (method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
},
'sameOrigin': function (url) {
return (url === origin || url.slice(0, origin.length + 1) === origin + '/') || (url === sr_origin || url.slice(0, sr_origin.length + 1) === sr_origin + '/') || !(/^(\/\/|http:|https:).*/.test(url));
},
'$setup': function () {
var scope = this;
// TODO: create server failure pages and alert mechanism
$.ajaxSetup({
statusCode: {
401: function () {
},
403: function () {
}
},
beforeSend: function (xhr, settings) {
if (!(scope.csrfSafeMethod(settings.type) && scope.sameOrigin(settings.url))) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
return this;
}
}());
$(document).ready(function(){
App.ajax.$setup()
var $form = $('form');
$form.on('submit' function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: '/dashboard',
data: $form.serialize(),
success: function (response) {
window.alert(response);
}
});
});
});
Personally I would prefer to pass JSON, also what browser are you testing in? Look into these libraries:
https://raw.github.com/marioizquierdo/jquery.serializeJSON/1.0.0/jquery.serializeJSON.js
https://raw.github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest/master/jQuery.XDomainRequest.js

Resources