I am trying to submit a form, but if I just put form_for #classroom I get a "No route matches [POST]" error.
Now with the code posted below, I get the wrong url in the form. If I change the url manually in the browser it goes through, and I guess I could do that via javascript, but... why... is... this... happening..?
Until yesterday everything was working fine. I even tried rolling back to the things I changed but I can't seem to track what is going wrong.
routes.rb
patch 'classrooms/:id/update' => "classrooms#update", as: :update_classroom
resources :classrooms, except: :update
form from rails end
<%= form_for(update_classroom_path(#classroom), method: "patch") do |class_f| %>
form in browser
<form action="/classrooms/23/edit" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓">
<input type="hidden" name="_method" value="patch">
<input type="hidden" name="authenticity_token" value="******">
rake routes
absences POST /absences(.:format) absences#create
POST /classrooms/:id/getAbsences(.:format) classrooms#getAbsences
update_classroom PATCH /classrooms/:id/update(.:format) classrooms#update
classrooms GET /classrooms(.:format) classrooms#index
POST /classrooms(.:format) classrooms#create
new_classroom GET /classrooms/new(.:format) classrooms#new
edit_classroom GET /classrooms/:id/edit(.:format) classrooms#edit
classroom GET /classrooms/:id(.:format) classrooms#show
DELETE /classrooms/:id(.:format) classrooms#destroy
root GET / pages#start
Just to answer your question from title, I think your form method is "PATCH" indeed. Refer to the guide http://guides.rubyonrails.org/form_helpers.html about how rails makes a patch form.
The Rails framework encourages RESTful design of your applications, which means you'll be making a lot of "PATCH" and "DELETE" requests (besides "GET" and "POST"). However, most browsers don't support methods other than "GET" and "POST" when it comes to submitting forms.
Rails works around this issue by emulating other methods over POST with a hidden input named "_method", which is set to reflect the desired method:
To add a bit of specificity, to Tashow's answer above (which set me on the right track), I had some hidden fields that look'd like this, in a nested form.:
<%= hidden_field_tag("Classroom[classroom_teachers_attributes][]", nil) %>
<%= hidden_field_tag("Classroom[classroom_teachers_attributes][]", '') %>
Once I got rid of these, everything began working properly again. (There still remained similar-looking <input> tags generated by fields_for, etc.)
After some more trial and error, I realised I had left some plain input tags in a deeper nested level of the form (instead of going with the normal fields_for and separate builders for each level). I guess that somehow screwed up the relations and affected the method of the parent form.
That was such a mind blending mess up.
Edit: Andylee's answer is right. What I and Jeremy mention was probably the actual issue going on and not what was originally assumed to be the problem (as mentioned in the title).
form_for takes an object as first argument, and its usually better to keep the REST-like way of rails handling the update method.
The action of you html form displays "/classrooms/23/edit" so yes it won't work.
form_for(#classroom, url: update_classroom_path(#classroom), method: "patch")
Related
After submitting my flaskapp form to make a new response, there is appears a 'quick-suggested' form contains previous input values. How can I restrict appearing this? In fact, I don't understand where it comes from and where it's stores so can't make a relevant ask to google. Dont be sarcastic - it was surprisingly for me, that it's disappear when I try to make this image with scissors!
it's all about that
P.S. all happens in google chrome
Your "google term" would be form autocomplete. This is a feature of your browser not flask or any web framework.
You can ask the browser to not autocomplete a form.
<form ... autocomplete="off">
or an individual field
<input type="text" autocomplete="off">
Keep in mind that the browser doesn't have to respect your wishes. Specifically in the case of login fields where browsers will autofill usernames and passwords regardless of autocomplete="off".
I have a form which I am validating using CFWheels model validation and form helpers.
My code for index() Action/View in controller:
public function index()
{
title = "Home";
forms = model("forms");
allforms = model("forms").findAll(order="id ASC");
}
#startFormTag(controller="form", action="init_form")#
<select class="form-control">
<option value="">Please select Form</option>
<cfloop query="allforms">
<option value="#allforms.id#">#allforms.name#</option>
</cfloop>
</select>
<input type="text" name="forms[name]" value="#forms.name#">
#errorMessageOn(objectName="forms", property="name")#
<button type="submit">Submit</button>
#endFormTag()#
This form is submitted to init_form() action and the code is :
public function init_form()
{
title = "Home";
forms = get_forms(params.forms);
if(isPost())
{
if(forms.hasErrors())
{
// don't want to retype allforms here ! but index page needs it
allforms = model(tables.forms).findAll(order="id ASC");
renderPage(action="index");
//redirectTo(action="index");
}
}
}
As you can see from the above code I am validating the value of form field and if any errors it is send to the original index page. My problem is that since I am rendering page, I also have to retype the other variables that page need such as "allforms" in this case for the drop down.
Is there a way not to type such variables? And if instead of renderPage() I use redirectTo(), then the errors don't show? Why is that?
Just to be clear, I want to send/redirect the page to original form and display error messages but I don't want to type other variables that are required to render that page? Is there are way.
Please let me know if you need more clarification.
This may seem a little off topic, but my guess is that this is an issue with the form being rendered using one controller (new) and processed using another (create) or in the case of updating, render using edit handle form using update.
I would argue, IMHO, etc... that the way that cfWheels routes are done leaves some room for improvement. You see in many of the various framework's routing components you can designate a different controller function for POST than your would use for GET. With cfWheels, all calls are handled based on the url, so a GET and a POST would be handled by the same controller if you use the same url (like when a form action is left blank).
This is the interaction as cfwheels does it:
While it is possible to change the way it does it, the documentation and tutorials you'll find seem to prefer this way of doing it.
TL; DR;
The workaround that is available, is to have the form be render (GET:new,edit) and processing (POST:create,update) handled by the same controller function (route). Within the function...
check if the user submitted using POST
if it is POST, run a private function (i.e. handle_create()) that handles the form
within the handle_create() function you can set up all your error checking and create the errors
if the function has no errors, create (or update) the model and optionally redirect to a success page
otherwise return an object/array of errors
make the result error object/array available to view
handle the form creation
In the view, if the errors are present, show them in the form or up top somewhere. Make sure that the form action either points to self or is empty. Giving the submit button a name and value can also help in determining whether a form was submitted.
This "pattern" works pretty well without sessions.
Otherwise you can use the Flash, as that is what it was created for, but you do need to have Sessions working. their use is described here: http://docs.cfwheels.org/docs/using-the-flash and here:http://docs.cfwheels.org/v1.4/docs/flashmessages
but it really is as easy as adding this to your controller
flashInsert(error="This is an error message.");
and this to your view
<cfif flashKeyExists("error")>
<p class="errorMessage">
#flash("error")#
</p>
</cfif>
I am having a login page for user generated by devise gem.where I removed the registerable from model for only login not for signup.I have also generated an admin which gives default login credentials for user in seed.rb file.I have done some css work in login page. next I have generated an employee page for further process for users.
Here my doubt is the styling part what I have done in login page is also coming in employee page. I dont want that so I wrote some condition in application.html.erb
<% unless user_signed_in? %>
<%= render 'layouts/heading' %>
<% end %>
The method is defined in application.controller.rb
def user_signed_in? %>
render :layouts => 'application'
end
I tried a lot by changing conditions but it is still displaying or showing errors.
You said that you're using "device gem", but since you're talking about authentication, I assume you mean "devise"?
The user_signed_in? method is a helper which should be provided automatically by devise, and you should be able to use it in your views. You shouldn't need to define it in the application controller.
You probably want to make sure you do "before_filter :authenticate_user!" in the relevant controller (you can use the ":only" option if you only want this to apply for certain methods).
It's difficult to give any more information because you haven't said what errors you are getting. I assume you're getting some kind of syntax error on the definition of the "user_signed_in?" method, since you have an invalid "%>"on the end of the line, which I guess you copied-and-pasted from an ERB file.
First Quesiton:
This form submits to demo_form?name=ABC
<form action="demo_form" method="get">
name: <input type="text" name="name"><br>
<input type="submit" value="Submit">
</form>
Is there a way to make it submit to demo_form/ABC/?
Second Question:
Even if users don't use my form, if they use a web crawler to simply visit demo_form?name=ABC or demo_form/ABC/, it would yield the same result. I want to prevent that. What's the best way of making those two URLs only valid if the user submit the name via my form? I am learning django so hopefully the solution would work with django framework.
Thanks in advance!
Is there a way to make it submit to demo_form/ABC/?
You could intercept the submission in JavaScript, construct the URL manually, then set location. That would break if JS wasn't available.
More sanely, you could send an HTTP 301 redirect response when you get the request for demo_form?name=ABC
What's the best way of making those two URLs only valid if the user submit the name via my form?
Generally speaking, visiting a form should not be a pre-requisite for anything involving a GET request. A large portion of the point of GET is that the results are bookmarkable, linkable, etc.
It would be more understandable if it was a POST request, as those are intended to change data on the server and you will want to protect against CSFR. The standard protection against CSRF is a token stored in the form and in a cookie
My company gave me the task of resolving all security issues with a particular application. The security tream reported a cross site scripting error. The error lies in the following input field:
<input type="hidden" name="eventId" value="${param.eventId}"/>
The report from security wasn't very detailed, but the say they can make a POST request to the page that has the above tag including the following malicious code:
eventId=%22%3e%3csCrIpT%3ealert(83676)%3c%2fsCrIpT%3e
And that when the page reloads, it will have the following:
<input type="hidden" name="eventId" value=""><sCrIpt>alert(83676)</sCrIpt></value>
I am trying to "be the hacker" and show the vulnerability. But I can't figure out how they manage to get that script in there. I am guessing they include it as a URL parameter in the GET request for the form, but when I try to do it myself I get a 403 error. Does anyone know how the vulnerability can be shown?
I know there is a number of XSS questions on the site, but none seem to hit this topic.
So, I am not sure why, but my original hunch was correct. The script can be put on as a URL parameter. For some reason though, this was not working with our staging site. Only with running the application locally. I am not sure why, but this works (only locally):
http://localhost:8080/myUrl/MyAction.do?eventId=%22%3e%3csCrIpT%3ealert(83676)%3c%2fsCrIpT%3e
Doing that, you see an alert box pop up. I am planning to fix it using JSTL functions.
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input type="hidden" name="eventId" value="${fn:escapeXml(param.eventId)}"/>
Install [TamperData][1] add-on in firefox browser which let you edit the data before submitting. Doesn't matter if it's in POST or GET.
By using this hidden fields can be edited.
What you want to do to fix the problem, is to HTMLAttributeEncode the value before putting it inside the value-attribute. See OWASP ESAPI or MS AntiXSS for methods for doing HTML attribute encoding.
Seeing how the attack string is URL encoding, I think you guess about including it as a GET parameter seems reasonable.
I used the OWASP ESAPI API as the legacy jsp's didn't have JSTL available. This is what I used:
<input type="hidden" name="dataValue" value="<%=ESAPI.encoder().encodeForHTMLAttribute(dataValue)%>">
You can also use the API to filter request.Parameter() which I also needed, as in:
String userURL = request.getParameter( "userURL" )
boolean isValidURL = ESAPI.validator().isValidInput("URLContext", userURL, "URL", 255, false);
if (isValidURL) {
link
}
and:
String name = (String) request.getParameter("name");
name = ESAPI.validator().getValidInput("name ", name , "SafeString", 35, true);