Forbidden Error In JavaScript Ajax Call in CakePHP 3 - javascript

I have Seen Similar Questions but I could not arrive at the solution. Please help on this code, I am new to javascript
My JavaScript Code :
function checkId(id_corpus){
var dataSet = {identity_number: id_corpus};
var requestUrl = appBaseUrl+'users/check-id-presence';
alert(id_corpus);
$.ajax({
type: "POST",
url: requestUrl,
data: dataSet,
success: function(result) {
if(result == false){
$('#ino').css('background-color', 'red');
$('#ino').css('color', 'black');
}
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
}
});
}
The Above JS code is called by the following CakePHP view:
$this->Form->input('identity_number', ['style' => 'background-color : black; color : #1798A5;', 'id' => 'ino', 'onkeypress' => 'checkId(this.val)']);
Following is the controller code
public function checkIdPresence()
{
$this->autoRender = false;
$id_corpus = $this->request->data['identity_number'];
$check = $this->Users->find()->where(['identity_number LIKE' => '%'.$id_corpus.'%']);
if((iterator_count($check)) > 0){
echo false; //Corpus Exists
}else{
echo true;
}
}
I am stuck in the "Forbidden Error", I would like to bring it to your notice that similar AJAX is being used by me for Image display(as shown below), it is not showing any error:
function fetch(user_id, photo, photo_dir)
{
var dataSet = {id: user_id};
var requestUrl = appBaseUrl+'users/admin-side-nav-details';
var imageUrl = 'http://localhost/media/images/users/photo/'+photo_dir+'/'+'100x100_'+photo;
$.ajax({
type: "POST",
url: requestUrl,
data: dataSet,
success: function(result) {
$('#display_info').html(result);
var image = "<img src ="+imageUrl+" />"
console.log(image);
$('#display_image').html(image);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
}
});
}
EDIT: My Auth Component setup :
public function initialize()
{
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => ['username' => 'email', 'password' => 'password']
]
],
'loginAction' => [
'controller' => 'Users',
'action' => 'login',
],
'authError' => 'Are you sure, you want to enter?',
'logoutAction' => [
'controller' => 'Users',
'action' => 'login',
],
]);

Check https://book.cakephp.org/3.0/en/controllers/components/authentication.html#handling-unauthenticated-requests. "If authenticator returns null, AuthComponent redirects user to the login action. If it’s an AJAX request and config ajaxLogin is specified that element is rendered else a 403 HTTP status code is returned."
It seems to me like you didn't specify any authorization scheme so according to https://book.cakephp.org/3.0/en/controllers/components/authentication.html#using-no-authorization "If you don’t use an authorization scheme, make sure to check authorization yourself in your controller’s beforeFilter or with another component."
You can make actions public (in beforeFilter or initialize) using:
// Allow all actions
$this->Auth->allow();
// Allow only the index action.
$this->Auth->allow('index');
// Allow only the view and index actions.
$this->Auth->allow(['view', 'index']);

Related

AJAX Post call no data

Hello wenn i want to send a post request to my Controller there is no data.
I tried to log my Json file and there is something. But when I send the post request my controller shows it is empty.
Here is my call:
var item = {};
var jsonObj = [];
item["ProductCategoryId"] = i;
item["Name"] = txtName;
item["Description"] = txtDescription;
item["Price"] = txtPrice;
item["Stock"] = txtStock;
item["ProductCategory"] = txtProductCategory;
item["Image"] = await getAsByteArray(txtImage);
jsonObj.push(item);
var jsonString = JSON.stringify(jsonObj);
console.log("jsonString : " + jsonString);
$.ajax({
url: "/Admin/SaveProductToDB",
type: "POST",
data: { dataToSend: jsonString},
success: function (data) {
if (data.status == "Success") {
BootstrapDialog.show({
title: 'Success!',
message: "Data Updated Successfully!",
buttons: [{
label: 'OK',
action: function (dialog) {
window.location.href = "/Admin/Product";
removeProdData(i);
$("#btnAddProd").attr("disabled",false);
dialog.close();
}
}]
});
}
}
});
//Here I make a breakpoint but my string is empty
public JsonResult SaveProductToDB(string dataToSend)
{
List<Product> _List = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Product>>(dataToSend);
}
the getAsByteArray
async function getAsByteArray(file) {
return new Uint8Array(await readFile(file))
}
function readFile(file) {
return new Promise((resolve, reject) => {
// Create file reader
let reader = new FileReader()
// Register event listeners
reader.addEventListener("loadend", e => resolve(e.target.result))
reader.addEventListener("error", reject)
// Read file
reader.readAsArrayBuffer(file)
})
}
I found out if I remove the Image. that the controller is then able to resize it. Thanks for the help so far. So I need to look at this place where the problem is.
You are checking against data.status as if it's a given that it exists. Just console.log(data) instead and you will see whether or not status is being returned.
Also, if you open the Network tab in Chrome you can click on the post request & see if your headers are going through accurately and also click on 'Preview' to see an unfiltered result from the controller.
You might want to modify your code to catch errors for debugging, ie:
$.ajax({
url: "/Admin/SaveProductToDB",
type: "POST",
data: { dataToSend: jsonString},
success: function (data) {
if (data.status == "Success") {
BootstrapDialog.show({
title: 'Success!',
message: "Data Updated Successfully!",
buttons: [{
label: 'OK',
action: function (dialog) {
window.location.href = "/Admin/Product";
removeProdData(i);
$("#btnAddProd").attr("disabled",false);
dialog.close();
}
}]
});
}
},
error:function (xhr, ajaxOptions, thrownError) {
// Set up whatever error reaction you want, here. ie:
console.log('An error was encountered.');
alert(xhr.status);
alert(thrownError);
}
});
Another tip is to validate empty data being submitted prior to the Ajax call, so you only touch the backend server when your data is valid - to avoid an error.

wordpress ajax rest api ("code":"rest_invalid_json","message":"Invalid JSON body passed.")

I dont understand what i did wrong, can anyone give me a suggestion on what causes the above error below is my code. I can confirm that, i am hitting the route, succesfully because the code inside get it executed. I am also adding the 1 value at the end, to be passed it to json as per wp_send_json_success. At this point i dont know what to next, can anyone explaint to me, on what is going on?
route.php
function update_employee_photo($request){
global $wpdb;
$data_with_photo = array(
'photo' => $request['photo'],
'photo_privacy' => $request['photoPrivacy'],
'photo_description' => $request['photoDescription']
);
$data_null_photo = array(
'photo_privacy' => $request['photoPrivacy'],
'photo_description' => $request['photoDescription']
);
$data = ($request['photo'] != "null") ? $data_with_photo : $data_null_photo;
$where = array('wp_user_id' => get_current_user_id());
$result = $wpdb->update("aupair_registered_employee", $data, $where);
if($result){
wp_send_json_success($result, 200, 1);
} else {
wp_send_json_error($wpdb->last_query);
}
die();
}
add_action('rest_api_init', function(){
register_rest_route( 'activeAupair/v1', '/updateEmployeePhoto', [
'methods' => 'POST',
'callback' => 'update_employee_photo'
]);
});
file.js
$.ajax({
type: 'POST',
url: myAjax.restURL + 'activeAupair/v1/updateEmployeePhoto',
contentType: 'application/json',
datatype: 'json',
data: {
photo: photo,
photoPrivacy: getPhotoPrivacy(),
photoDescription: getPhotoDescription()
},
beforeSend: function (xhr) {
xhr.setRequestHeader('X-WP-Nonce', myAjax.nonce);
},
success: function(response){
console.log('TYPE OF ', typeof response);
console.log('RESPONSE ', response);
msg.empty();
msg.append($('<p id="required"></p>').text('Updated'));
uploadBtn.attr('value', 'Update');
uploadBtn.attr('disabled', false);
},
error: function (xhr, ajaxOptions, thrownError) {
},
complete: function(data){
console.log('COMPLETE ', data);
}
});
As per the wordpress wp_send_json_success() function expect third parameter 1(default 0) to encode it into JSON format (see the reference). So you need to pass the status code as second parameter and 1 for the JSON object.
wp_send_json_success($result, 200, 1);

Post Image with ajax in laravel 5.6

I want to create an upload adapter for ckeditor,
I have an issue in my laravel ajax application,
here is my code.
export default class UploadAdapter {
constructor(loader) {
this.loader = loader;
}
upload() {
return new Promise((resolve, reject) => {
let data = new FormData();
data.append('upload', this.loader.file);
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: '/loadImage',
type: 'POST',
data: data,
dataType: 'json',
async:false,
processData: false,
contentType: false,
success: function (data) {
console.log(data.get('upload'));
},
error: function (request, status, error) {
console.log(error);
}
});
});
}
}
I stuck in responding with ajax to laravel controller.
Here is my Controller function:
try {
$file = $request->file('upload');
$uploader = MediaUploader::fromSource($file);
$uploader->setAllowedMimeTypes(['image/jpeg', 'image/gif', 'image/png']);
$uploader->setAllowedExtensions(['jpg', 'jpeg', 'png', 'gif']);
$media = $uploader->upload();
return response()->json([
'uploaded' => true,
'url' => $media->getUrl()
]);
} catch (\Exception $e) {
return response()->json(
[
'uploaded' => false,
'error' => [
'message' => $e->getMessage()
]
]
);
}
Here is my error
SyntaxError: Unexpected end of JSON input
at parse (<anonymous>)
at ajaxConvert (app.js:11826)
at done (app.js:12294)
at XMLHttpRequest.<anonymous> (app.js:12587)
What is the error in my code ???
I cant get the file information in laravel controller..
How can i solve this issue...? Help me Please!!!
You have data - empty
JSON.parse(''); // SyntaxError: Unexpected end of input
Add verification:
data = data != "" ? $.parseJSON(data) : {};

AJAX if JSON-response = X -> do action

I am working on a site and now I am at the point that I have to make the AJAX-forms. The code I have now does insert the params in the database, but now I get stuck at the following point. I want my code to hide the form after the status of JSON is success. Working in a MVC. This is my code:
(I have let the unimportant part of the code away)
AJAX:
$("#submitAssignment").on("click", function () {
$.ajax({
type: "POST",
url: "/set/new/ass",
async: true,
data: data,
success: function (data) {
console.log("Het item is toegevoegd");
var err = jQuery.parseJSON(data);
sendAlert.createAlert(err.return, err.type);
if (jsonObj.status == 'success') {
$("#submitAssignment").hide();
}
}
});
});
Controller:
else {
$UserModel = new UserModel();
if ($UserModel->placeAssignment($title, $uploadable, $level, $points, $description)) {
$err['data'] = array("status" => "success", "type" => "success", "return" => "De opdracht is toegevoegd! Joepie :D" );
} else {
$err['data'] = array("status" => "failed", "type" => "danger", "return" => "Er is iets misgegaan!");
}
}
exit( $err['endpoint'] = json_encode( $err['data'], $options = 0 ) );
The part I want to hide after status = succes, does not hide, so thats my problem. I have searched other questions, but aint got success with that. What am I doing wrong in this case?
The problem in this case is that I used the wrong call-back in the ajax-code. I used JSONobj.status, but it need to be: err.status because I am handling it at that way. #timothyGroote gave this answer and now it works.
My ajax-code now:
$.ajax({
type: "POST",
url: "/set/new/ass",
async: true,
data: data,
success: function (data) {
console.log("Het item is toegevoegd");
var err = jQuery.parseJSON(data);
sendAlert.createAlert(err.return, err.type);
if (err.status == 'success') {
$("#submitAssignment").hide();
}
}
});

Loading remote data only once with Select2

As the title suggests I would like to load remote data once only.
I thought about loading a data with independent ajax call and set it "locally" at the control but wonder if there is more "built in" way to do so...
a solution can be found here:
https://github.com/ivaynberg/select2/issues/110
$("#selIUT").select2({
cacheDataSource: [],
placeholder: "Please enter the name",
query: function(query) {
self = this;
var key = query.term;
var cachedData = self.cacheDataSource[key];
if(cachedData) {
query.callback({results: cachedData.result});
return;
} else {
$.ajax({
url: '/ajax/suggest/',
data: { q : query.term },
dataType: 'json',
type: 'GET',
success: function(data) {
self.cacheDataSource[key] = data;
query.callback({results: data.result});
}
})
}
},
width: '250px',
formatResult: formatResult,
formatSelection: formatSelection,
dropdownCssClass: "bigdrop",
escapeMarkup: function (m) { return m; }
});
Edit:
I might have misinterpreted your question. if you wish to load all data once, then use that is Select2, there is no built in functionality to do that.
Your suggestion to do a single query, and then use that stored data in Select2 would be the way to go.
This is for Select2 v4.0.3:
I had this same question and got around it by triggering an AJAX call and using the data returned as the initialized data array.
// I used an onClick event to fire the AJAX, but this can be attached to any event.
// Ensure ajax call is done *ONCE* with the "one" method.
$('#mySelect').one('click', function(e) {
// Text to let user know data is being loaded for long requests.
$('#mySelect option:eq(0)').text('Data is being loaded...');
$.ajax({
type: 'POST',
url: '/RetrieveDropdownOptions',
data: {}, // Any data that is needed to pass to the controller
dataType: 'json',
success: function(returnedData) {
// Clear the notification text of the option.
$('#mySelect option:eq(0)').text('');
// Initialize the Select2 with the data returned from the AJAX.
$('#mySelect').select2({ data: returnedData });
// Open the Select2.
$('#mySelect').select2('open');
}
});
// Blur the select to register the text change of the option.
$(this).blur();
});
This worked well for what I had in mind. Hope this helps people searching with the same question.
To load data once:
Assumptions:
You have a REST API endpoint at /services that serves a JSON array of objects
The array contains objects which have at least a "name" and "id" attribute. Example:
[{"id": 0, "name": "Foo"}, {"id": 1, "name": "Bar"}]
You want to store that array as the global 'services_raw'
First, our function to load the data and create the global 'services_raw' (AKA 'window.services_raw'):
fetchFromAPI = function() {
console.log("fetchFromAPI called");
var jqxhr = $.ajax(
{
dataType:'json',
type: 'GET',
url: "/services",
success: function(data, textStatus, jqXHR) {
services_raw = data;
console.log("rosetta.fn.fetchServicesFromAPI SUCCESS");
rosetta.fn.refreshServicesSelect();
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("Error inside rosetta.fn.fetchServicesFromAPI", errorThrown, textStatus, jqXHR);
setTimeout(rosetta.fn.fetchServicesFromAPI(), 3000); // retry in 3 seconds
}
}
)
.done(function () {
console.log("success");
console.log(jqxhr);
})
.fail(function () {
console.log("error");
})
.always(function () {
console.log("complete");
});
// Perform other work here ...
// Set another completion function for the request above
jqxhr.always(function () {
console.log("second complete");
});
};
Second, our Select2 instantiation code which transforms our data into a format that Select2 can work with:
refreshServicesSelect = function () {
// ref: http://jsfiddle.net/RVnfn/2/
// ref2: http://jsfiddle.net/RVnfn/101/ # mine
// ref3: http://jsfiddle.net/RVnfn/102/ # also mine
console.log('refreshServicesSelect called');
$("#add-service-select-service").select2({
// allowClear: true
data: function() {
var arr = []; // container for the results we're returning to Select2 for display
for (var idx in services_raw) {
var item = services_raw[idx];
arr.push({
id: item.id,
text: item.name,
_raw: item // for convenience
});
}
return {results: arr};
}
});
};
Here's what the Select2 element in HTML should look like before your call the above functions:
<input id="add-service-select-service" type="hidden" style="width:100%">
To use all of this, call (in JS):
window.fetchFromAPI();
window.refreshServicesSelect();
Lastly, here's a JSFiddle where you can play with a similar thing: http://jsfiddle.net/RVnfn/102/
Basically, in my example above, we're just using ajax to populate the equivalent of window.pills in the Fiddle.
Hope this helps :)
Please reply if you know how to do this via the Select2 .ajax function, as that would be a bit shorter.
In my condition, it is working perfectly with the given code
$('#itemid').select2({
cacheDataSource: [],
closeOnSelect: true,
minimumInputLength: 3,
placeholder: "Search Barcode / Name",
query: function(query) {
// console.log(query);
self = this;
var key = query.term;
var cachedData = self.cacheDataSource[key];
if(cachedData) {
query.callback({results: cachedData});
return;
} else {
$.ajax({
url: "./includes/getItemSelect2.php",
data: { value : query.term },
dataType: 'json',
type: 'POST',
success: function(data) {
self.cacheDataSource[key] = data;
query.callback({results: data});
}
});
}
},
});
And my data return from the ajax is in this form
<?php
$arr = [
["id" => 1, "text" => "Testing"],
["id" => 2, "text" => "test2"],
["id" => 3, "text" => "test3"],
["id" => 4, "text" => "test4"],
["id" => 5, "text" => "test5"]
];
echo json_encode($arr);
exit();
?>

Categories