Yii : What can block access to $_POST data? - post

I am sending a post to a controller / action (not ajax).
Inside the action, I am doing the standard way of checking to see if it was a post (the exact way works in other actions I am using).
if( isset( $_POST['LessonForm'] ) )
{
...
}
else
{
Yii::trace( "Post Not Set" );
}
And the post is always not set.
However, if I put a var_dump( $_POST ); die(); in front of the conditional, I get this:
array(2) { ["LessonForm"]=> array(3) { ["title"]=> string(4) "test" ["shortDescription"]=> string(4) "test" ["image"]=> string(0) "" } ["yt1"]=> string(0) "" }
So the post is clearly there. Furthermore,
foreach( $_POST as $key => $value )
{
echo( $key.'<br>' );
}
I get this:
LessonForm
yt1
Further suggesting the post is there.
When trying to use the variable in $_POST, it is not there. If accessing it in a foreach loop and assigning it to a variable, I can vardump the variable but not use it.
To test if it was a accessControl problem, I removed all filters.
What can block access like this?
Update:
#Stu is correct in that it is not being sent as a POST. The form method is post. Not sure how else to force a post?
Update 2:
Problem is fixed, but I'm still not sure what was causing the CActiveForm to send a get rather than post and still include post data.
After removing the transaction from the model save, the problem vanished (it should not have been there in the first place).
Update 3:
The original problem was an actionCreate. That problem mysteriously vanished. Next was an actionEdit. The view rendered (with the form) is the same file. The action was copied and pasted with modifications as to how the data was being saved and getting the model rather than making a new one.
After looking at the network traffic, there is a post followed immediately by a 302 redirect that isn't in my code. For some reason Yii is forcing a 302 redirect to get to the action.

Yii has already abstracted out getting request variables whether they're POST or GET
Use: Yii::app()->request->getParam('SomeVarName', 'ADefaultValue');
To get a request variable and returning a sensible default if one doesn't exist. If you're having trouble sending the variables from the form in the first place though, that could be a different issue.

Related

My Stimulus checkbox script in Rails 7 doesn't work

I'm learning stimulus and trying to get add a checkbox feature where you can mark an order as complete from the show page without using a form. I followed this tutorial, but am not getting the correct results. The checkbox does nothing when clicked and unchecks when refreshed; however if I manually set the complete attribute to true, the checkbox is automatically checked when loading the page, as it should.
I have a model "Order" with a boolean attribute "complete". Here's my show.html.erb section
<tr data-controller="todo" data-todo-update-url="<%= order_path(#order.id) %>">
<td>
<div>
<input type="checkbox"
data-action="todo#toggle"
data-target="todo.completed"
<% if #order.complete %> checked <% end %> >
</div>
</td>
</tr>
Here's my stimulus todo_controller
import { Controller } from "#hotwired/stimulus"
export default class extends Controller {
static targets = [ "completed" ]
toggle(event) {
// Inside the toggle(event) function, let’s start by getting the value of the checkbox,
// and put it into a FormData object
let formData = new FormData()
formData.append("#order[complete]", this.completedTarget.completed);
// Let’s post that data to the "update-url" value we set on the Todo row.
// We’ll set the method to PATCH so that it gets routed to our todo#update on our controller.
// The credentials and headers included ensure we send the session cookie and the CSRF protection token and
// and prevent an ActionController::InvalidAuthenticityToken error.
fetch(this.data.get("update-url"), {
body: formData,
method: 'PATCH',
dataType: 'script',
credentials: "include",
headers: {
"X-CSRF-Token": getMetaValue("csrf-token")
}
})
// We can take the Response object and verify that our request was successful.
// If there was an error, we’ll revert the checkbox change.
.then(function(response) {
if (response.status != 204) {
event.target.complete = !event.target.complete
}
})
}
}
Can someone tell me where my code is going wrong?
This is more a long comment than a solution but few things I see :
You create an empty form and append a single input with name
"#order[complete]" though your Stimulus controller is Javascript
and has no knowledge of # the such way you use in Ruby. Also params
names are usually model[field] then I think you don't need the #.
"order[complete]" should be fine.
Also you grab the value from a specific target for the aforementionned value with this.completedTarget.completed. Should you not rather pick the value of the input field ? and rather grab this.completedTarget.value or maybe the checked status this.completedTarget.checked
You are getting the URL to your fetch from a data attribute. I am not a stimulus expert but it doesn't look like anything Stimulus related. As of now you have written it this.data.get("update-url") but in regular javascript, something like this.element.dataset.todoUpdateUrl should work.
And just to be sure there is no confusion to about where you will
call this , just declare it at the top of your Stimulus methd like
this : var backUrl = this.element.dataset.todoUpdateUrl. And fill the url to your fetch as just fetch(backUrl,...
you pass the formData directly to your fetch body. If this doesn't work, try to stringify it and extract the entries like : JSON.stringify(Object.fromEntries(formData)). Also I am not too sure about the dataType: 'script', you may just omit that alltogether.
There may be other problems that I don't see. Also when you are dealing with JS, don't only look to your Rails console, especially if nothing hits the backend. Open the developper / inspect tool in your browser and monitor the console there, you should see all the XHR (async) requests made to your app.
If nothing happens, then your fetch is not firing and there need to be more investigations made..

How to set a work item state while creating or updating work item in Azure Devops Rest API?

I have been working to create an API which programatically creates/updates work item in Azure Devops. I have been able to create a work item and populate almost all fields. I have problem with setting the state.
When I am creating a POST request to Azure Devops rest api with any state name like "Active", "Closed", "Rejected", it throws a 400 Bad Request error.
I don't know if I am missing anything or if there something wrong with the way I am trying to set the value.
{
"op" : "add",
"path": "/fields/System.State",
"value"="Active",
}
I have found the solution to this problem and hence I am answering it here.
I was getting a 400 Bad Request error whenever I tried Creating an Item and Setting the state in the same call. I debugged the code and caught the exception. I found out that, there are some validation rules for some of the fields. State is one of them.
The rule for System.State field is, whenever a Work Item is created it takes its configured default value. ( In my case it was "Proposed", in your case it could be "New"). If you try altering the value at the time of work item creation, it throws a 400 Bad Request.
What should I do if I have to Create a Work Item with a specific State?
As of now, the solution that I have found out is to make two calls. One for Work Item Creation and another for Changing the state of the work item to desired state.
CreateWorkItem()
{
var result = await _client.Post(url, jsonData);
var result2 = await _client.Put(result.id, jsonData); // or maybe just the state
return Ok(result2);
}
Check the example here: Update a field
You have to use "value":"Active" in the request body.
[
{
"op" : "add",
"path": "/fields/System.State",
"value": "Active"
}
]

Kohana 3.3 get url parameters

My question can look stupid but I need to get in touch and get a decision. I want to pass parameters to url without the parameters being seen in the url. this is to secure my server. Because the url looks like this
controller/edit/123
and the '123' is the user ID in the database.
I can simple do this
public function action_edit($id) {
get_db_info($id);
}
Is it possible to hide the parameter while redirecting to this url from a view? ie in the view file
// Do something to set the ID
<?php Kohana_Request::post("user_id", $id); ?>
Click
and get the ID like this
public function action_edit() {
$id = $this->request->post("user_id");
get_db_info($id);
}
But the problem I can't access the KOhana_Request instance and get this error
*Non-static method Kohana_Request::post() should not be called statically*
Can someone gives a secured approach to this ?
I think I found a solution by encoding and decoding the parameters.
Since Kohana 3.3 do not allow parameters in controller functions see .
I do this in my view
$user_id = Encrypt::instance()->encode($liste->user_id);
$encode_id = base64_encode($user_id);
$encode_ure_id = urlencode($encode_id);
And from the controller,
$encoded_id = urldecode($this->request->param('uri_id'));
$encode_base_url = base64_decode($encoded_id);
$user_id = Encrypt::instance()->decode($encode_base_url);
If this can help others.

Pass an & as Part of a Route Parameter

Unfortunately I need to accept a route parameter with an & in it. I have this route definition. The id parameter will sometimes have an & in it like this X&Y001.
routes.MapRoute(
"AffiliateEdit",
"Admin/EditAffiliate/{*id}",
new { controller = "UserAdministration", action = "EditAffiliate", id = ""}
);
I have tried working around this issue in the following ways however none of them have worked. All of these result in an HTTP 400 Bad Request error in the browser.
Edit
This gives me Edit
<%= Html.RouteLink("Edit", "AffiliateEdit", new { id = a.CustomerID }) %>
This gives me Edit
<%= Html.RouteLink("Edit", "AffiliateEdit", new { id = Url.Encode(a.CustomerID) }) %>
This gives me Edit
the only thing I can think of (which is a "dirty" solution) is to encode the & yourself. for example something like ##26##.
make sure to check the decoding algorithm only decodes the & ids and not some id that happens to contain ##26## for example.
A better solution depending on db size is to change the offending ids in the database.

form serialize problem

I have a form. I am trying to validate it through AJAX GET requests.
So i am trying to send the field values in the GET request data.
$('#uxMyForm').serialize();
the problem it is returning something undecipherable. I have used serialize before. This is totally bizzare.
the return value of serialize is
actionsign_upcontrollersitedataauthenticity_token=oRKIDOlPRqfnRehedcRRD7WXt6%2FQ0zLeQqwIahJZJfE%3D&customer%5BuxName%5D=&customer%5BuxEmail%5D=&customer%5BuxResidentialPhone%5D=&customer%5BuxMobilePhone%5D=&customer%5BuxDateOfBirth%5D=&customer%5BuxAddress%5D=&customer%5BuxResidentialStatus%5D=
i have no idea how to use this.
Thanks
update:
My question is how do i process such a request? like this?
puts params[:data][:customer][:uxName]
my GET request trigger looks like this
$.get('/site/sign_up',{data : $('#uxMyForm').serialize() }, function(data){
alert(data);
});
The above jquery lines generate the request.. on the action method i do the following
render :text => params
when i observe what is sent in the GET,in firebug PARAMS
**data** authenticity_token=oRKIDOlPRqfnRehedcRRD7WXt6%2FQ0zLeQqwIahJZJfE%3D&direct_customer%5BuxName%5D=&direct_customer%5BuxEmail%5D=&direct_customer%5BuxResidentialPhone%5D=&direct_customer%5BuxMobilePhone%5D=&direct_customer%5BuxDateOfBirth%5D=&direct_customer%5BuxAddress%5D=&direct_customer%5BuxResidentialStatus%5D=
the return value that i print in alert has
actionsign_upcontrollersitedataauthenticity_token=oRKIDOlPRqfnRehedcRRD7WXt6%2FQ0zLeQqwIahJZJfE%3D&direct_customer%5BuxName%5D=&direct_customer%5BuxEmail%5D=&direct_customer%5BuxResidentialPhone%5D=&direct_customer%5BuxMobilePhone%5D=&direct_customer%5BuxDateOfBirth%5D=&direct_customer%5BuxAddress%5D=&direct_customer%5BuxResidentialStatus%5D=
How does the form itself look. I have no experience with Ruby on rails - and if it builds the form in a new exciting way - but it looks as if there's only two form elements: authenticity_token and customer - where customer is an array of items. This is the data you posted, but I urldecoded it and put in some linebreaks:
authenticity_token=oRKIDOlPRqfnRehedcRRD7WXt6/Q0zLeQqwIahJZJfE=
&customer[uxName]=
&customer[uxEmail]=
&customer[uxResidentialPhone]=
&customer[uxMobilePhone]=
&customer[uxDateOfBirth]=
&customer[uxAddress]=
&customer[uxResidentialStatus]=
What you could do is to serialize the form to an array and clean it up before sending it using jQuery ajax request. I did something similar once when I had to serialize .net runat-server form elements:
var serializedData = $(form).serializeArray();
for( i=0; i < serializedData.length; i++)
{
// For each item in the array I get the input-field name after the last $ character
var name = serializedData[i].name;
var value = serializedData[i].value;
if( name.indexOf('$') != -1)
name = name.substr( name.lastIndexOf('$')+1 );
serializedData[i].name = name;
}
var ajaxPostData = $.param(serializedData);
So instad of blabla$ABCPlaceHolder$tbxEmail I got tbxEmail in the array. You could do the same to get uxName, uxEmail etc instead of the customer array.
Note then again, however, due to my inexperience with ruby that this may not be the best solution - maybe there's a setting you can change to build the HTML form differently?
Updated:
I'm not sure how ruby works, but after a googling I found you should be able to receive your values using params:customer as an array.
params:customer should contain an array of the values
{:uxName => "", :uxEmail => "" }
I hope that tells you something on how to receive the data. Maybe (warning - wild guess!) like this?
params[:customer][:uxName]

Resources