Use devise password to restrict method in a controller - ruby-on-rails

I am trying to restrict some of my user's action with their user account password.
I have a transfer controller, and users can transfer money using the create method in the transfer controller.
I would like to require the password everytime the user click on the transfer button to validate the transfer but I could not find anything related to that on the web.
I want to add a password field to the views and process the transfer only if the password is the user account password.
I am using devise for managing my users account.
How could I do that ?
Thanks,
Form :
<%= form_for current_user.transfers.build do |f| %>
<div class="amount">
<h5>Select an amount</h5>
<div class="amount-btns">
<a class="amount-btn" href="#"><span data-amount="10">10$</span></a>
<a class="amount-btn" href="#"><span data-amount="20">20$</span></a>
<a class="amount-btn" href="#"><span data-amount="30">30$</span></a>
<a class="amount-btn" href="#"><span data-amount="50">50$</span></a>
<%= f.hidden_field :amount, :id => :amount %>
<%#= f.hidden_field :teen_id , :id => :user_id_auto_donation %>
</div>
</div>
<div class="choose-amount">
<div class="choose-amnt" action="#">
<div class="form-row choose-lnk">
<%= f.collection_select :teen_id, current_user.followed_users, :id, :first_name , include_blank: false, :prompt => 'Select a Teen' %>
</div>
<%= hidden_field_tag :no_card if !current_user.customer_id? %>
<%= password_field(:password, :password, :size => 20, :class => 'form_input') %>
<%= f.submit 'Send', :class => "orange-btn", :id => "send_donation"%>
<% end %>
Transfer_Controller :
def create
Rails.logger.debug(params[:password])
Rails.logger.debug(current_user.valid_password?(params[:password]))
if current_user.valid_password?(params[:password])
....
else
redirect_to :back
end
Rails.logger.debug(params[:password]) return the password I entered and the one that is correct.
Rails.logger.debug(current_user.valid_password?(params[:password])) return false but if I relplace the params[:password] with the actual password it return true
Thanks for your help !

I found this link that shows you how to check user credentials,
for your case you will do something like the following (given that you send the password as a parameter named 'password'):
# use the return value to determine if the user inserted the correct password
if(current_user.valid_password?(params[:password]))
# create transfer
else
# tell user password is invalid
end

Related

How do I validate text_field_tag when is not part of the model in Ruby on Rails?

I'm creating a wedding rsvp application and have ran into a problem. I have an RSVP Model with some fields then in my form I have added an extra text field (text_field_tag) that does not belong to the RSVP Model, however I want to validate it in my rsvp.rb model to make it required.
The extra field is a "code" field (as seen below) that I will be providing in the wedding invitations.
I also want to "compare" the entered "code" in my controller rsvp_controller.rb to the valid static code upon rsvp creation.
new.html.erb
<%= form_for(#rsvp, :html => { class: 'form-horizontal', role: 'form' }) do |r| %>
<div class="form-group">
<div class="control-label pull-left">
<%= r.label :party, 'Name' %> <span class="required">*</span>
</div>
<div class="control-label">
<%= r.text_field :party, class: 'form-control', placeholder: 'Individual or family name', autofocus: true %>
</div>
</div>
...
<div class="form-group">
<div class="control-label pull-left">
<label for="rsvp_code">Enter code found in invitation</label> <span class="required">*</span>
</div>
<div class="control-label">
<%= text_field_tag 'rsvp_code', nil, class: 'form-control' %>
</div>
</div>
...
<% end %>
rsvp_controller.rb
def create
#rsvp = Rsvp.new(rsvp_params)
#compare the values of the text field to invitation code
#if values match then proceed
#else send error message
if #rsvp.save
flash[:success] = 'Thank you'
redirect_to root_path
else
render 'new'
end
end
rsvp.rb
class Rsvp < ActiveRecord::Base
validates text_field_tag presence: true #or something like this
end
The others answers here will work. But they are very messy. Validations belong on the model.
class Rsvp < ActiveRecord::Base
attr_accessor :rsvp_code
validates :rsvp_code, presence: true
end
You will also need to change your form from: <%= text_field_tag 'rsvp_code', nil, class: 'form-control' %> to <%= f.text_field :rsvp_code, class: 'form-control' %>
Read more on attr_accessor
Since the value is not stored in the model, it doesn't make sense to validate it in there. Add this logic in your controller instead. And depending on the way you store your "static code" your controller logic shoud look like this :
def create
if params["rsvp_code"] == "YOUR_CODE"
Rsvp.new(rsvp_params)
...
else
flash["error"] = 'Your invitation code does\'t match'
redirect_to rsvp_new_path
end
end

Form not working on Access Denied redirection in Rails 4

I'm working on a Rails 4 web application, using Devise and CanCanCan.
When a user first signs up to create an account, they are redirected to a subscription page where they enter in credit card details, etc.
User Creation -> Subscription Creation = Form works
This is working absolutely perfectly and once they enter in their subscription information, a permission change is made on their account and they can then access a new part of the site. All good.
Now the issue I am having is, if a user signs up, then tries to access this new part of the site without subscribing, I redirect them to the subscription page. However when I do this, the form just doesn't work. They hit submit and nothing happens.
User Creation -> Tries to access resource, gets redirected to
Subscription Creation = Form doesn't work
Here is the code I am using to perform the redirection:
application_controller.rb
def access_denied(exception)
redirect_to(new_subscription_path, alert: exception.message + " Please subscribe.")
end
The strange thing is that I am using the exact same code to redirect when they first create a user account. This is shown here:
registrations_controller.rb
def after_sign_up_path_for(resource)
new_subscription_path
end
Here is the code for the subscription controller:
class SubscriptionsController < ApplicationController
before_filter :authenticate_user!
def new
#subscription = Subscription.new
end
def create
#subscription = Subscription.new(subscription_params)
#user = current_user
#subscription.user_id = current_user.id
if #subscription.save_with_payment
redirect_to success_path, :notice => "Thank you for subscribing!"
if current_user.role = "guest"
User.update(current_user.id, role: "read")
end
UserMailer.subscription_welcome_email(#user).deliver
else
render :new
end
end
def show
#subscription = Subscription.find(params[:id])
end
def destroy
#subscription = Subscription.find_by(user_id: current_user.id)
User.update(current_user.id, role: "guest")
unless #subscription.stripe_customer_id.nil?
customer = Stripe::Customer.retrieve(#subscription.stripe_customer_id)
customer.subscriptions.retrieve(customer.subscriptions.first.id).delete
end
#user = current_user
UserMailer.subscription_destroy_email(#user).deliver
#subscription.destroy
rescue Stripe::StripeError => e
logger.error "Stripe Error: " + e.message
errors.add :base, "Unable to cancel your subscription. #{e.message}."
false
end
def subscription_params
params.require(:subscription).permit(:stripe_card_token, :last_4_digits, :plan, :expiry_month, :expiry_year)
end
end
Form code:
<div class='panel panel-default'>
<div class='panel-heading'>
<h2>Subscribe</h2>
</div>
<div class='panel-body'>
<%= semantic_form_for #subscription, :html => {:class => 'main-form'} do |f| %>
<font color=red><b><%= f.semantic_errors *f.object.errors.keys %></b></font>
<%= f.hidden_field :stripe_card_token %>
<div id='stripe_error' class="alert alert-info" style='display:none'>
</div>
<span class="help-block">Nothing is billed to your card for 7 days. <b>Guaranteed. </b>
<br>If you choose to continue after 7 days, only then will you be billed.</span>
<div class='form-group'>
<%= label_tag :card_number, "Credit Card Number" %><%= image_tag "welcome/checkout/amex.png", alt: "American Express", class: "credit-card-image" %><%= image_tag "welcome/checkout/mastercard.png", alt: "Mastercard", class: "credit-card-image" %><%= image_tag "welcome/checkout/visa.png", alt: "Visa", class: "credit-card-image" %>
<%= text_field_tag :card_number, nil, name: nil, class: 'form-control input-box', :placeholder => 'Credit Card Number' %>
</div>
<div class='row'>
<div class="col-xs-6">
<%= label_tag :card_code, "Security Code on Card (CVC)" %><%= image_tag "welcome/checkout/credit.png", alt: "Credit Card Image", class: "credit-card-image" %>
<%= text_field_tag :card_code, nil, name: nil, class: 'form-control input-box', :placeholder => 'Security Code on Card (CVC)' %>
</div>
<div class="col-xs-6">
<%= label_tag :card_month, "Card Expiration" %><br>
<%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month", class: 'expiration'} %>
<%= select_year nil, {start_year: Date.today.year+1, end_year: Date.today.year+15}, {name: nil, id: "card_year", class: 'expiration'} %>
</div>
</div>
</div>
<div id="stripe_error">
<noscript>JavaScript is not enabled and is required for this form. First enable it in your web browser settings.</noscript>
</div>
<div>
<%= f.submit "Subscribe", class: 'btn standard-button' %>
</div>
<% end %>
</div>
</div>
Can anyone assist? Let me know if any extra code is required. Thanks
EDIT: Just to make things weird, this error is only happening when I hit a link in my navigation that is new_subscription_path .. the access denied works fine if I type in manually the URL of the permissioned resource. Could there be something wrong with the path I am using in the header? Do I need to pass something specific into it? I've also tried to check if it was JavaScript by adding in a console log, but nothing comes through, so I don't think this is an issue, despite it feeling like a JS issue.
You should check you javascript. Clearly it blocks form from submission. I've looked at your previous question here and it looks like your handleStripeResponse handler always goes into else condition block not submitting form as the result. My bet is that $('meta[name="stripe-key"]').attr('content') is undefined after your redirection.
Disabled Turbolinks solved this problem

Rails - add elements to array using text_field

I want to do something that should be really simple: use an input text field to add elements to an array. As simple as it may seem, I'm kind of stuck...
Each User has a (single) Profile. Each Profile contains a text-field 'entertainment' that is serialized as an array in the ProfilesController.
I got as far as updating the attribute with a fixed text by using the following:
method in the ProfilesController
def update_entertainment
#user = User.find_by(params[:id])
#profile = #user.profile
#user.profile.update(entertainment: ["the usual suspects"])
redirect_to profile_path(current_user, tab:"entertainment")
end
profile_params in the ProfilesController
def profile_params
params.require(:profile).permit(:gender, :date_of_birth, :zip_code, :city, :state, :country, :marital_status, :entertainment )
end
the form
<div class="form-group">
<%= text_field :entertainment, :class => 'form-control' %>
<%= button_to("+", :action => :update_entertainment, :method => :put, :remote => true) %>
</div>
However, whatever I've tried (and that is a lot), I cannot manage to PUSH (not just update) the input of a text-field to the array. For now adding one element at a time will do. What I really want to do is give users the opportunity to ADD elements to the array.
I'm using Rails 4.0.x
The reason was in using button_to instead of usual form.
Normal form instead of button_to solved the problem.
SOLVED
With the help of #D.K. and #anushka I was able to solve the issue. I changed the changed the line
#profile.entertainment << params[:entertainment]
in the ProfilesController to
#profile.entertainment << params[:entertainment]
and changed the form to this:
<div class="form-group">
<%= form_tag(:action => :update_entertainment, :method=>'post', :multipart => true, :class => 'form-control') do %>
<div class="input-group">
<%= text_field_tag :entertainment, nil, :class => 'form-control form-group', :placeholder => 'add interests' %>
<span class="input-group-btn">
<%= submit_tag '+', class: 'btn btn-default' %>
</span>
</div>
<% end %>
</div>

Stripe withdrawal action in rails marketplace app

I'm new to rails. I'm trying to create a rails marketplace where sellers can cash out their acquired funds from sales on the site.
I'm confused how to configure my withdrawal form and my orders controller.
When I simply just go to localhost:3000/withdrawal, a Stripe Recipient with just name is created on my Stripe dashboard without even completing the form. My form is nonexistent because everything I've tried for form_for generates an error.
I want the user to input their info and then choose to submit it, not create the recipient when "cash out" (which leads to the withdrawal path) is clicked.
The stripe documentation is helpful, but I'm not sure how to create my form.
Here is my withdrawal action in my orders controller. I'm wondering if I need a new action within withdrawal? But not sure if that's possible?
def withdrawal
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
recipient = Stripe::Recipient.create(
:name => current_user.full_name,
:type => "individual",
:bank_account => token
)
transfer = Stripe::Transfer.create(
:amount => (#funds).floor,
:currency => "usd",
:recipient => #seller.recipient
)
end
And my withdrawal.html.erb. I know I am missing a form tag and submit, but everything I've tried just processes an error. I don't know what form_for to call. I've tried "order" but it results in an error.
<div class="text-center">
<h1>Bank Account Information</h1>
<div class="form-group">
<%= label_tag :name %>
<%= text_field_tag :name, nil, { :name => nil, :'data-stripe' => "name", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :withdrawal_amount %>
<%= text_field_tag :withdrawal_amount, nil, { :name => nil, :'data-stripe' => "amount", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :routing_number %>
<%= text_field_tag :routing_number, nil, { :name => nil, :'data-stripe' => "routingNumber", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :account_number %>
<%= text_field_tag :account_number, nil, { :name => nil, :'data-stripe' => "accountNumber", class: "form-control" } %>
</div>
I'd appreciate any guidance on how to create this "cash out" action. Thanks.
form_for is for model objects. If you're not using a model object, or don't want/need Rails to infer things from the model object, don't use form_for.
For simple forms, instead use one of:
form_tag - Same syntax as form_for but without the model-related magic.
A plain old <FORM> tag. ERB templates are, after all, just HTML with Ruby mixed in.
Your view should look something like the following:
<%= form_tag withdrawl_path, method: :post do %>
<input type="text" name="card[number]" />
<!-- whatever fields you need for form -->
<% end %>
You will be able to access the submitted params via params[:card][:param_name] or use strong params and only permit params you need.
Use custom routes
get "/form" => "controller_name#action_for_form", as: :action_for_form
post "/withdrawl" => "controller_name#withdrawl", as: :withdrawl
Controller:
def action_for_form
# whatever code you need to setup form
#seller = Seller.find(params[:seller_id])
end
def withdrawl
# withdrawl code here
end
private
def card_params
params[:card].permit(:card_token, :other_params)
end
Its worth taking the time to understand the form tag and using Rails outside of the Railsy way of form submissions. It can get messy, but it allows for much more flexibility.

Use key in params

I am trying to build a log in system by this tutorial:
http://www.youtube.com/watch?v=h0k6DFIStFY
My form looks like this:
<!DOCTYPE html>
<div id="content">
<%= flash[:alert1] %>
<%= form_for(:sessions, :url => sessions_path , :html => {:id => "login-form"}) do |f| %>
<fieldset>
<p>
<%= label_tag :name ,"Username:" %>
<%= text_field_tag :name, params[:name] , :class => "round full-width-input", :autofocus=>true %>
</p>
<p>
<%= label_tag :password, "Password:" %>
<%= password_field_tag :password, params[:password], :class => "round full-width-input" %>
</p>
<%= submit_tag "Login", :class=> "button round blue image-right ic-right-arrow" %>
</fieldset>
<% if (flash[:status] == FALSE) %>
<br/><div class="information-box round"><%= flash[:alert] %></div>
<% end %>
<% end %>
</div> <!-- end content -->
and my controller looks like this:
class SessionsController < ApplicationController
def login
end
def create
user = User.authenticated?(params[:sessions][:name], params[:sessions][:password])
flash[:alert1] = "dummy"
if user
redirect_to '/login'
else
flash[:status] = FALSE
flash[:alert] = "Invalid username and password"
redirect_to '/login'
end
end
def new
end
end
when trying to submit, i get this error:
undefined method `[]' for nil:NilClass
in the following line:
user = User.authenticated?(params[:session][:name], params[:session][:password])
Did i use incurrectly in the session key ?
Thanks,
Gal!
I think you have some problems in your form: you are using a form_for and then in fields you are using text_field_tag.
I would correct it in something like :
<% form_for sessions .... do |f| %>
<%= f.text_field :name %>
and so forth.
This will generate the params you want in your controller
params[:sessions][:name]
params[:sessions][:password]
I would suggest you to use some gem instead of building an entire system of authentication, which can be quite tricky in terms of security. Have you taken a look at https://github.com/plataformatec/devise?
Hope it helps
It looks like you're using an external authentication gem, perhaps one of these?
https://www.ruby-toolbox.com/categories/rails_authentication
You need to include a require <gem_name> line at the top.

Resources