submit from HAML form clears session data (Rails3)? - ruby-on-rails-3

I have the following model:
Project
- name:text
- description:text
And this is snippet of the form I've written in HAML for new project:
%p Create a new project:
%form{:method => "post", :action=>"/projects/"}
%label{:for => "project-name[name]"} Name:
%input{:type=>'text', :size=>40, :name=>'projectname', :id=>'project-name'}
%br/
%label{:for => "project-description[description]"} Description:
%textarea{:rows=>'10',:cols=>'10',:name=>'projectdescription',:id=>'project-description'}
%br/
%input{:type=>'submit', :value=>'Create'}
when the user clicks submit, the session data seems to be cleared.
Here is why I suspect this:
I am using omniauth, when a user signs in, I set session[:user_id] = user.id
I have a redirect in the project controller for ensuring the user is always signed in for all actions
the index and new actions are handled properly.
instead of the create action being handled, the user is bounced to the sign in page (as per the before_filter)
I replicated the same functionality with erb files and there no issue. When I drop in the new.haml file the error shows up again.
Any ideas?

I believe that what's happening here, is that you have `protect_from_forgery' in your ApplicationController, but the csrf token is not sent to application. Check if you have a relevant rails.js included if it's AJAX call. And if you were using form_for, then the helper would automatically insert the hidden field with the csrf token.

Related

Devise #token not resolving correctly (Devise 3.2.3)

Running a Rails 4 app with Devise 3.2.3 and Devise Confirmable.
Devise generates a confirmation_token for a newly created user that is correctly stored in the database, and then sends out a mailer with confirmation instructions. The token sent out in the mailer is different than the confirmation_token stored in the db for security reasons, but the token sent out in the mailer is not resolving to the correct confirmation token for the user, therefore the user is never confirmed.
Here is an example of what I am talking about:
The user in the database has the following confirmation_token attr set by Devise after being created:
beaa0ed7c9c2da72a99381ee705aa8ebd91672a5c18f5a44deeb43d0665080c4
and the following link is sent out in an email to the user:
http://localhost:3000/users/confirmation?confirmation_token=ZEagTsW1o1Ex_xGdQq7D
I have confirmed that the template for the mailer is using the new #token method instead of the old #resource.confirmation_token
%p Welcome #{#email}!
%p You can confirm your account email through the link below:
%p= link_to 'Confirm my account', confirmation_url(#resource, confirmation_token: #token)
but when I hit the link that devise sends out, the #token does not resolve to the correct confirmation_token attr on the user. From the logs:
Started GET "/users/confirmation?confirmation_token=ZEagTsW1o1Ex_xGdQq7D" for 127.0.0.1 at 2014-04-16 12:15:33 -0700
Processing by ConfirmationsController#show as HTML
Parameters: {"confirmation_token"=>"ZEagTsW1o1Ex_xGdQq7D"}
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`confirmation_token` = 'd876b3a89e02512b7c8ff632f2d8ff33dbe57ccc4df50469ad99e456c45938f8' ORDER BY `users`.`id` ASC LIMIT 1
As you can see, the #token sent out in the email resolved to d876b3a89e02512b7c8ff632f2d8ff33dbe57ccc4df50469ad99e456c45938f8 instead of beaa0ed7c9c2da72a99381ee705aa8ebd91672a5c18f5a44deeb43d0665080c4. Any ideas?
Answered this question after banging my head against this for a while. I had an after_create callback on my user model that was updating an attribute on the user and that was causing Devise to internally regenerate the confirmation_token after the confirmation_instructions email was sent out, therefore the token in the email was no longer current or valid.

Rails 3 form actions and methods

I have made a resource.
resources :dashboards
I have a partial file which contains a form and I want to use this partial (as the form elements won't change) to update and create. So here is what I have:
Controller
class DashboardsController < ApplicationController
def new
#dashboard = Dashboard.new
end
end
View
/dashboards/new.html.erb
<%= render :partial => "form", :locals => { :dashboard => #dashboard } %>
Partial Form
/dashboards/_form.html.erb
<%= form_for(#dashboard) do |form| %>
.....
<% end %>
Ruby Guide
The Ruby Guide states:
The Article model is directly available to users of the application, so — following the best practices for developing with Rails — you should declare it a resource. When dealing with RESTful resources, calls to form_for can get significantly easier if you rely on record identification. In short, you can just pass the model instance and have Rails figure out model name and the rest. For example:
## Creating a new article
# long-style:
form_for(#article, :url => articles_path)
# same thing, short-style (record identification gets used):
form_for(#article)
## Editing an existing article
# long-style:
form_for(#article, :url => article_path(#article), :html => { :method => "put" })
# short-style:
form_for(#article)
Result
I thought I have followed the Rails Guide correctly. Because I made #dashboard a resource. I could just pass it into the form and have it handle the action, method and the rest. Instead I'm getting this:
<form accept-charset="UTF-8" action="/dashboards" class="new_dashboard" id="new_dashboard_" method="post">
According to the docs. Shouldn't the action of my form now be "/dashboards/new" because we are on the new action? And should it be passing an extra field declaring the method to be put when I use the same code in the /edit action??
My result is always the same no matter what. The form never changes.
What am I doing wrong?
EDIT
Here is my router info from rake routes
GET /dashboards(.:format) dashboards#index
POST /dashboards(.:format) dashboards#create
GET /dashboards/new(.:format) dashboards#new
GET /dashboards/:id/edit(.:format) dashboards#edit
GET /dashboards/:id(.:format) dashboards#show
PUT /dashboards/:id(.:format) dashboards#update
DELETE /dashboards/:id(.:format) dashboards#destroy
You are correct that you should be able to "pass #dashboard into the form and have it handle the action, method and the rest." The issue here is what new is in the context of RESTful actions.
When you declare a set of resources with resources :dashboards, you are creating a set of routes which map requests to controller actions:
GET /dashboards index
GET /dashboards/new new
POST /dashboards create
GET /dashboards/:id show
GET /dashboards/:id/edit edit
PUT /dashboards/:id update
DELETE /dashboards/:id destroy
You can check this if you run rake routes.
The issue here is that the new action is defined as a GET request to the path /dashboards/new, i.e. this is the route for the form itself. The URL in the action attribute of the actual form is something else: this is where the form will post the data to with a POST request, which on the server (rails) side will map to the create controller action.
When you use the form helper with form_for(dashboard), a form is created with a route corresponding to what dashboard is: if it is a new record (i.e. it does not yet exist in the database), then the form action will be create (and point to /dashboards), whereas if it already exists it will point to the actual URL for the record (e.g. /dashboards/123). This is what makes the form helpers so useful.
So, to sum up, /dashboards is the correct URL, not for the new action but for the create action, which the form helper uses because dashboard is a new record. new is the route to the page where the form resides, i.e. /dashboards/new.
Hope that makes sense.
p.s. as a side note, you shouldn't be accessing #dashboard in the partial if you are passing it in as a local (:locals => { :dashboard => #dashboard }). Just use dashboard.

Active admin change default model admin_user

I'm starting my first project with Active Admin.
To use another model for my users I use the following command :
rails generate active_admin:install User
After this I make this change in active_admin initializer :
config.authentication_method = :authenticate_user!
config.current_user_method = :current_user
I'm correctly login my application but on the home page I get this error :
undefined method `destroy_admin_user_session_path' for #<ActiveAdmin::Views::HeaderRenderer:0x007ff8fa086a60>
How can I fix it properly ?
Solved by editing initializer :
config.logout_link_path = :destroy_user_session_path
This is addition to #Awea answer. Use togather with that.
Check rails routing table for destroy_user_session.
For example devise token auth make route table entry like this:
destroy_user_session DELETE /auth/sign_out(.:format) devise_token_auth/sessions#destroy
But default method for activeadmin logout link is :get and it will not work.
To make it worked properly add to config/initializers/active_admin.rb also and:
config.logout_link_method = :delete

No POST from facebook using real-time updates in Rails, Heroku and Koala

This question is an expanded version of Facebook Real-time updated does not call our servers, that seems to be dead. Also, Realtime updates internal server error on Heroku using Koala is not helpful because I'm subscribing from the heroku console as pjaspers suggested.
I have an app (ruby 1.9.2p290 and Rails 3.1.3) that connects to facebook to get data from the current user. Everything is working ok with the koala gem (v1.2.1), but I'm polling the fb servers every time the users logs in. I would like to use facebook real-time updates, and I have read the following:
Koala manual on fb realtime updates: https://github.com/arsduo/koala/wiki/Realtime-Updates
Facebook page on realtime: https://developers.facebook.com/docs/reference/api/realtime/
I have set up the system in test mode and deployed to heroku successfully. I can subscribe to the user object and I get the GET request to my server, but no POST with updated information is ever received from facebook. If I issue a POST to my server manually everything works.
More information:
routes.rb
get '/realtime' => 'realtime#verify'
post '/realtime' => 'realtime#change'
generating
realtime GET /realtime(.:format) {:controller=>"realtime", :action=>"verify"}
POST /realtime(.:format) {:controller=>"realtime", :action=>"change"}
The controller (mock version, only to test if it's working):
class RealtimeController < ApplicationController
def verify
render :text => params["hub.challenge"]
end
def change
puts params.inspect
render :nothing => true
end
end
The subscription from the heroku console:
irb(main):004:0> #updates = Koala::Facebook::RealtimeUpdates.new(:app_id => ENV['FACEBOOK_APP_ID'], :secret => ENV['FACEBOOK_APP_SECRET'])
=> #<Koala::Facebook::RealtimeUpdates:0x00000004f5bca8 #app_id="XXXXXXX", #app_access_token="XXXXXXX", #secret="XXXXXXX", #graph_api=#<Koala::Facebook::API:0x00000004a8d7a8 #access_token="XXXXXXX">>
irb(main):005:0> #updates.list_subscriptions
=> [{"object"=>"user", "callback_url"=>"http://blah-blah-0000.herokuapp.com/realtime", "fields"=>["education", "email", "friends", "name", "website", "work"], "active"=>true}]
I don't know what to do next...
Maybe I am not triggering the correct changing events?
How do I see the list of users of my app? (right now it's a test app and the only user would be me)
Anyone with this kind of issue?
Is something wrong in the code?
Is facebook down? Is it the end of Internet?
Thank you for the help :)
You need to respond to the GET request with a challenge response. I have the same route for both POST and GET requests and use the following code:
route:
match "facebook/subscription", :controller => :facebook, :action => :subscription, :as => 'facebook_subscription', :via => [:get,:post]
controller:
def realtime_request?(request)
((request.method == "GET" && params['hub.mode'].present?) ||
(request.method == "POST" && request.headers['X-Hub-Signature'].present?))
end
def subscription
if(realtime_request?(request))
case request.method
when "GET"
challenge = Koala::Facebook::RealtimeUpdates.meet_challenge(params,'SOME_TOKEN_HERE')
if(challenge)
render :text => challenge
else
render :text => 'Failed to authorize facebook challenge request'
end
when "POST"
case params['object']
# Do logic here...
render :text => 'Thanks for the update.'
end
end
end
That should get you going with things... Note that to make a subscription I am using this:
#access_token ||= Koala::Facebook::OAuth.new(FACEBOOK_API_KEY,FACEBOOK_API_SECRET).get_app_access_token
#realtime = Koala::Facebook::RealtimeUpdates.new(:app_id => FACEBOOK_API_KEY, :app_access_token => #access_token)
#realtime.subscribe('user', 'first_name,uid,etc...', facebook_subscription_url,'SOME_TOKEN_HERE')
I think the key is that you properly respond to the GET request from Facebook. They use this to verify that they are contacting the correct server prior to sending confidential info about their users.
Also -- its been a while since I've looked at this, but if I remember correctly, I seem to recall having issues with anything besides default protocol port specifications within the callback URL. Ex: http://www.something.com:8080/subscription did not work -- it had to be http://www.something.com/subscription
Not sure if this might be the case with you, but make sure that you have permissions to access the object -user, permissions, page- properties (location, email, etc.)
In my case, I was trying to get notifications for changes on the location property without my app requiring the user_location permission. For the user object, look at the Fields section in this page https://developers.facebook.com/docs/reference/api/user/
Does Facebook know where your application is? Does it have a URL that it can resolve?

Create New User with info from another Model - Rails 3.0

I am using Rails 3 and Devise for user authentication. I created a separate scaffold, request_new_user, and I want to have a link on the index page for all of the people who requested an account to go to the new_user_path, with their information sent as well to populate the fields. How would I set the params so I can set the values within the user controller? Or is there a better way to do this? I mainly just want to pass the new user's name and email.
You can generate devise views in your project by: rails generate devise:views .
Send your params in GET request: /signup?email=...&name=...
In registration view you can apply your params, something like:
<%= f.input :email, :value => params[:email] %>
Hope it helps.