Unauthorize error on password update Devise - ruby-on-rails

I'm working on a rails api and using devise_token_auth for the authentication, when I try to update password by hitting the /auth/password with put request it responsds with error 401 i.e. unauthorized. My server logs show me this
Started PUT "/auth/password" Processing by
DeviseTokenAuth::PasswordsController#update as HTML Parameters:
{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}
Can't verify CSRF token authenticity Completed 401 Unauthorized in
routes.rb
mount_devise_token_auth_for 'User', at: 'auth' ,:controllers => { :omniauth_callbacks => 'omniauth' }
view.html (angularjs)
<div class="container">
<div class="row">
<div class="row">
<div class="col-xs-6 col-xs-offset-3 que">
<img src="./uploads/img/web-logo.png" class="img-responsive" alt="Logo">
</div>
</div>
<div class="col-xs-12 reset-pas">
<form name="update_pass" ng-submit="updatePassword_controller()" role="form" class="lost_reset_password">
<p class="error_msg" ng-show="update_pass.password_confirmation.$error.passwordVerify">
Passwords are not equal!
</p>
<label>New password</label>
<input type="password" name="password" ng-minlength="8" ng-model="updatePasswordForm.password" required="required" class="form-control">
<span>Minimum 8 Charachters</span>
<br>
<label>Re-enter new password</label>
<input type="password" name="password_confirmation" ng-minlength="8" ng-model="updatePasswordForm.password_confirmation" required="required" class="form-control" password-verify="updatePasswordForm.password" >
<button type="submit" class="btn btn-default" id="reset-submit">Save</button>
</form>
</div>
</div>
</div>
controller.js
$scope.updatePassword_controller = function() {
$auth.updatePassword($scope.updatePasswordForm)
.then(function(resp) {
console.log(resp)
$location.path('/')
})
.catch(function(resp) {
console.log(resp)
});
};
Update
Note
I'm facing this issue only for password update
Update
I installed gem 'angular_rails_csrf' Now it's giving only the authorization error not the csrf attack error

Use the Rails form_tag or form_for helpers. They add will add a hidden field for the XCSRF token:
<div class="container">
<div class="row">
<div class="row">
<div class="col-xs-6 col-xs-offset-3 que">
<img src="./uploads/img/web-logo.png" class="img-responsive" alt="Logo">
</div>
</div>
<div class="col-xs-12 reset-pas">
<%= form_tag "#", { "ng-submit" => "updatePassword_controller()", "role" => "form", "class" => "lost_reset_password"} do %>
<p class="error_msg" ng-show="update_pass.password_confirmation.$error.passwordVerify">
Passwords are not equal!
</p>
<label>New password</label>
<input type="password" name="password" ng-minlength="8" ng-model="updatePasswordForm.password" required="required" class="form-control">
<span>Minimum 8 Charachters</span>
<br>
<label>Re-enter new password</label>
<input type="password" name="password_confirmation" ng-minlength="8" ng-model="updatePasswordForm.password_confirmation" required="required" class="form-control" password-verify="updatePasswordForm.password" >
<button type="submit" class="btn btn-default" id="reset-submit">Save</button>
</form>
</div>
</div>
</div>

I simply made a condition in applicationcontroller.rb like below and it worked out . The main idea is simply to override the functionality of Devise
if params[:controller] == "devise_token_auth/passwords" && params[:action] == "update"
uri = URI.parse(request.headers.env['HTTP_REFERER'])
query_params = CGI.parse(uri.query)
email = query_params['uid'].first
user = User.find_by_email(email)
user.password = params[:password]
user.password_confirmation = params[:password_confirmation]
if user.save
render json: {message: 'Password Updated successfully', status: 200}
else
render json: {message: 'Password Could not changed , Please contact to support Team', status: 401}
end
end
Although it's not the proper solution but i couldn't think of anyother one . So please bear with me .In it we're fetching email from url

Related

Calling method in rails

In my application I have an form to create new company. Here I have to enter company name and company url.Here is my code for the from.
<%= form_tag(controller: "/company", action: "add_startup_to_index", method: "post") do %>
<div class="modal-body">
<div class="form-group">
<label class="control-label">Company Name</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Enter the name of the company..." required />
</div>
<div class="form-group">
<label class="control-label">Company URL</label>
<input type="text" class="form-control" id="url" name="url" placeholder="e.g. http://www.company.com..." required />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-conf" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary btn-conf">Add Company</button>
</div>
<% end %>
This is my method for saving above data.
def add_startup_to_index
#url = api_version_root + 'startups/new'
response = RestClient.post #url,
{ startup: { friendly_name: params[:name],
url: params[:url]
}
}, api_token_hash
record = JSON.parse(response.body)
flash[:info] = 'Startup has been added and Crunchbase sync started.'
redirect_to('/startups/' + record['company_id']) && return
rescue RestClient::ExceptionWithResponse => err
handle_rest_error http_code: err.http_code
end
This is working fine and I can save the companies. Now I want to validate the URL. For that I have below method.
def valid_url?(url)
return false if url.include?("<script")
url_regexp = /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
url =~ url_regexp ? true : false
end
Since I am new for rails I have no idea how to call that method within my form. I had tried nested form_tag. But it is now allowed.
I tried as below.
<%= form_tag(controller: "/company", action: "add_startup_to_index", method: "post") do %>
<div class="modal-body">
<div class="form-group">
<label class="control-label">Company Name</label>
<input type="text" class="form-control" id="name" name="name" placeholder="Enter the name of the company..." required />
</div>
<%= form_tag(controller: "/company", action: "valid_url", method: "post") do %>
<div class="form-group">
<label class="control-label">Company URL</label>
<input type="text" class="form-control" id="url" name="url" placeholder="e.g. http://www.company.com..." required />
</div>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-conf" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary btn-conf">Add Company</button>
</div>
<% end %>
Can any one help me for this.
Lanka, if I understand you correctly, what you are looking for is client side form validation. Before HTML5 this was a tedious task involving JS. With HTML5, url validation is baked right in. Simply try to change the type of the input to url, i.e. change
<input type="text" id="url" name="url" ...>
to
<input type="url" id="url" name="url" ...>
Then, when a non-conforming url string is entered, the browser will not submit the form and automatically indicate the issue. This even works out of the box with a default url pattern. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/url for more information on custom patterns, placeholders and much more.

how to update user in ruby on rails

I am trying to update user info and i am having error that it didn't get any data from my form
Here is my user.controller:
def update
if !session[:id]
redirect_to '/users'
else
#user = User.find(params[:id])
#user.update(update_params)
if #user.valid?
#user.save
redirect_to '/events'
else
flash[:errors] = #user.errors.full_messages
redirect_to "/users/#{#user.id}/edit"
end
end
end
def update_params
params.require(:user).permit(:fname, :lname, :email, :city, :state)
end
edit update form
here is my edit.html.erb form:
<form action="/users/<%= #user.id %>/update" method="post">
<input type="hidden" name="_method" value="patch">
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
<div class="form-group row">
<label for="fname" class="col-sm-2 col-form-label">First Name</label>
<div class="col-sm-10">
<input type="text" name="user[fname]" class="form-control" placeholder="<%= #user.fname %>">
</div>
</div>
<div class="form-group row">
<label for="lname" class="col-sm-2 col-form-label">Last Name</label>
<div class="col-sm-10">
<input type="text" name="user[lname]" class="form-control" placeholder="<%= #user.lname %>">
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" name="user[email]" class="form-control" placeholder="<%= #user.email %>">
</div>
</div>
<div class="form-group row">
<label for="location" class="col-sm-2 col-form-label">Location</label>
<div class="col-sm-5">
<input type="text" name="user[city]" class="form-control" placeholder="<%= #user.city %>">
</div>
<div class="col-sm-5">
<select class="custom-select" name="user[state]">
<%= options_for_select(us_states)%>
</select>
</div>
</div>
<div class="form-group row clearfix">
<div class="col-sm-10 offset-sm-2">
<button type="submit" class="btn btn-primary float-right">Update</button>
</div>
</div>
</form>
Just updated my html form
this is error in terminal when i hit submit from my form:
(0.1ms) begin transaction User Exists (1.7ms) SELECT 1 AS one
FROM "users" WHERE ("users"."email" = 'nhan13574#gmail.com' AND
"users"."id" != 1) LIMIT 1 (0.1ms) rollback transaction Redirected
to http://localhost:4000/users/1/edit
Can you share the form? mostly the issue is there.
Also, #user.update actually saves the data in db, no need to save after it.. here is a refactored version of your snippet:
def update
return redirect_to '/users' unless session[:id]
#user = User.find(params[:id])
if #user.update(update_params)
redirect_to '/events'
else
flash[:errors] = #user.errors.full_messages
redirect_to "/users/#{#user.id}/edit"
end
end

Form validation in ruby on rails

I have built a sign up page in ruby on rails. I want to validate this sign up form. For example - if user left any section blank, the form will show an error message. It will also check whether the given email is unique. How can I do this by not changing my form?
#This my logins_controller.rb file
class LoginsController < ApplicationController
skip_before_action :verify_authenticity_token
def index
#subscriber=Subscriber.new()
end
def sign_up
subscriberNew = Subscriber.new
subscriberNew.name = params[:name]
subscriberNew.cus_user_name = params[:user_name]
subscriberNew.cus_password = params[:password]
subscriberNew.cus_email = params[:email]
result = subscriberNew.save
respond_to do |format|
msg = { :status => "ok", :message => "Success!" }
format.json { render :json => msg }
end
end
def validate_signup
#what should i write here?
end
end
and this is my sign up form
<div class="container">
<div class="shadow-lg p-3 mb-5 bg-white rounded view-card">
<h4 class="card-title">
<a href="/product_types">
<i class="material-icons">
arrow_back_ios
</i></a></h4>
<form id="signup_form" method="post" action="/sign-up">
<p class="h4 mb-4">Register to Binimoy</p>
<label for="name">Name</label>
<input type="text" name="name" id="name" class="form-control mb-4" placeholder="Name">
<label for="email">Email</label>
<input type="email" name="email" id="email" class="form-control mb-4" placeholder="Email">
<label for="phone">Phone</label>
<input type="text" name="phone" id="phone" class="form-control mb-4" placeholder="Phone">
<label for="name">Password</label>
<input type="password" name="password" id="password" class="form-control mb-4" placeholder="Password">
<div class="form-row mb-4">
<div class="col">
<button class="btn btn-default my-4 btn-block" type="reset">Reset</button>
</div>
<div class="col">
<button type="button" class="btn btn-info my-4 btn-block" id="submitAnchor">Submit</button>
</div>
</div>
</form>
</div>
First, use Rails helpers in your views and write your form as documented here.
<%= form_with url: sign_up_path do |form| %>
<%= form.label :email %>
<%= form.text_field :email %>
...
<%= form.submit %>
<% end %>
Second, use validations in your Subscriber model as documented here.
validates :email, presence: true, uniqueness: true
...
Hope it helps ;)
Rails is an framework with an strong opinion how to do things. You are doing things not the Rails way and this will make it more complicated.
If you really do not want to change your form (which is strongly advice against)
Add validations, check the return value of save and send back some error message
In your model:
validates :email, presence: true, uniqueness: true
In your controller:
if subscriber.save
render json: {status: "ok", message: "success"}
else
render json: {status: "nok", message: "something went wrong"}
end
Probably you should get rid of the status property and use the HTTP status code for this (sending back 201 (created) and 422 (unprocessble entity) responses instead)
Some other recommendatations to make your code more readable:
Follow the Rails conventions (use a form builder, it simplifies the assignment of form params to the model
Use Ruby naming conventions:
subscriberNew
should be
subscriber_new
since Ruby uses camel_case
but actually there is no need for the new suffix, so subscriber is enough
Use two spaces for identation
Don't abbreviate variables (cus_username, ...) and don't prefix when there is no need

Stripe different plans

So I got stripe up and running, however I have 3 different payment plans.
I'd like to capture what plan they clicked on, and use that to connect them to their right plan id.
This is what my form looks like:
<%= form_tag charges_path, id: "payment-form" do %>
<span class="payment-errors"></span>
<div class="form-row">
<label>
<span>Card Number</span>
<input type="text" size="20" data-stripe="number" maxlength="20" />
</label>
</div>
<div class="form-row">
<label>
<span>CVC</span>
<input type="text" size="4" data-stripe="cvc" maxlength="4"/>
</label>
</div>
<div class="form-row">
<label>
<span>Expiration (MM/YYYY)</span>
<input type="text" size="2" data-stripe="exp-month" maxlength="2"/>
</label>
<span> / </span>
<input type="text" size="4" data-stripe="exp-year" maxlength="4"/>
</div>
<button type="submit">Submit Payment</button>
<% end %>
I link to them like this:
<%= link_to 'Start Your Free Trial', new_charge_path(:plan_id => 1) %>
and the controller looks like this:
def create
customer = Stripe::Customer.create(
:email => 'exaimple#stripe.com',
:plan => plan_id,
:card => params[:stripeToken]
)
current_user.update_attributes(:stripe_customer_token => customer.id)
redirect_to root_url, notice: 'Successfully subscribed'
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to charges_path
end
which results in the error:
undefined local variable or method `plan_id'

In scraping, can't login with Mechanize

My aim: On ROR 3, get a PDF file from a site which requires you to login before you can download it
My method:
Step 1: log in to the site with Mechanize
Step 2: since I'm logged in, get the PDF with Nokogiri
Apparently, the login didn't succeed because I get nothing when I debug (pretty sure that the nokogiri part works well, already tested)
Below my code:
My Controller.rb
begin
# login to the scraped site:
agent = Mechanize.new
agent.get("http://elwatan.com/sso/inscription/inscription_payant.php")
#look for the wanted form
form = puts agent.page.parser.css('form')[1]
#login
agent.page.forms[1]["login"] = "my_login"
agent.page.forms[1]["password"] = "my_password"
agent.page.forms[1].submit
#scrape with nokogiri
docwatan = Nokogiri::HTML(open('http://www.elwatan.com/'))
#watan = {}
docwatan.xpath('//th/a').each do |link|
#watan[link.text.strip] = link['href']
end
My View.rb
<ul id= "list">
<% if #watan %>
<% #watan.each do |key, value| %>
<li class="List" ><a href="http://www.elwatan.com/<%= "#{value}" %>" target='_blank'> <%= "#{key}" %></a></li><% end %>
<% end %>
and the login form, from the scraped site
<form method="post" action="/sso/login.php" id="form-login-page">
<div id="form-login-container-page" style="color:red;text- align:center;width:100%;margin:10px 0"></div>
<input type="hidden" name="minimalist" value="1"><input type="hidden" name="SSO_Context" value=""><div class="clear"> </div>
<label>Email<span>*</span></label>
<div class="insc-saisie">
<input class="insc-saisie-champ" type="text" id="login-page" name="login" value="">
</div>
<div class="clear"> </div>
<label>Mot de passe<span>*</span></label>
<div class="insc-saisie">
<input class="insc-saisie-champ" type="password" id="password-page" name="password" value="">
</div>
<div class="clear"> </div>
<label><input type="checkbox" unchecked=""></label>
<div class="insc-saisie">Se souvenir</div>
<div class="clear"> </div>
<label> </label>
<div class="insc-saisie">
Mot de passe oublié ?
</div>
<div class="clear"> </div>
<label> </label>
<div class="insc-saisie">
<input class="b-connexion" type="image" src="/img/trans.gif">
</div>
<div class="clear"> </div>
<div class="clear"> </div>
<label><span>*</span></label>
<div class="insc-saisie">Saisie obligatoire</div>
<div class="clear"> </div>
</form>
kinhdly notice that the login is done on this page "http://elwatan.com/sso/inscription/inscription_payant.php", and the download from "http://elwatan.com"; could be important
Thanks in advance
Instead of:
docwatan = Nokogiri::HTML(open('http://www.elwatan.com/'))
You want to do:
docwatan = agent.get('http://www.elwatan.com/')
otherwise the session cookie isn't getting sent in the request.

Resources