In scraping, can't login with Mechanize - ruby-on-rails

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.

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.

Ckeditor ruby gem adds ">" at the end of the entries every time a user edits the textarea entry

Ckeditor ruby gem is adding a ">" at the end of my content entries every time a user edits the content.
Here is a video of it happening: https://drive.google.com/file/d/16sus8LGxHBZLFs_ts5_SJJSwLfisJzom/view?usp=sharing
Here is my update_row controller code for the text_component model. The textarea input is being saved in the content column.
def update_row
#text_component = TextComponent.find(params.fetch("id_to_modify"))
#text_component.tab_id = params.fetch("tab_id")
#text_component.content = params.fetch("content")
if #text_component.valid?
#text_component.save
redirect_to("/guides/"+params.fetch("guide_id"), :notice => "Text component updated successfully.")
else
#guide = Guide.find(params.fetch("guide_id"))
render("guide_templates/show.html.erb")
end
end
ANSWERED: here is the working form code in my edit_form view:
<form action="/update_text_component/<%= #text_component.id %>" method="post">
<!--input for guide_id -->
<div class="form-group">
<input type="hidden" id="guide_id" name="guide_id" class="form-control" value="<%= params.fetch("guide_id") %>">
</div>
<!-- input for tab_id -->
<div class="form-group">
<input type="hidden" id="tab_id" name="tab_id" class="form-control" value="<%= params.fetch("tab_id") %>">
</div>
<div class="form-group">
<label for="content">
Content
</label>
<textarea id="content" name="content" class="ckeditor" rows="10"><%= raw #text_component.content %></textarea>
</div>
<button class="btn btn-block btn-outline-secondary">
Update text component
</button>
</form>
<form action="/update_text_component/<%= #text_component.id %>" method="post">
<!--input for guide_id -->
<div class="form-group">
<input type="hidden" id="guide_id" name="guide_id" class="form-control" value="<%= params.fetch("guide_id") %>">
</div>
<!-- input for tab_id -->
<div class="form-group">
<input type="hidden" id="tab_id" name="tab_id" class="form-control" value="<%= params.fetch("tab_id") %>">
</div>
<div class="form-group">
<label for="content">
Content
</label>
<textarea id="content" name="content" class="ckeditor" rows="10"><%= raw #text_component.content %></textarea>
</div>
<button class="btn btn-block btn-outline-secondary">
Update text component
</button>
</form>

Adding a new Favorite: Creating a form with the current_user.id

I'm trying to create a form that will save the current_user.id. Something is funky in my controller. Any thoughts on obvious issues?
View (new.html.erb)
<!-- Label and input for user_id -->
<div class="form-group">
<label for="user_id" class="control-label">
User
</label>
<%= current_user.id %>
<input type="hidden" name="user_id" value="<%= current_user.id%>">
</div>
Controller (favorites_controller.rb)
def create
#favorite = Favorite.new
#favorite.dish_comment = params[:dish_comment]
#favorite.user_id = curent_user.id
d = params[:dish_id]
r = params[:restaurant_id]
problem code:
#favorite.user_id = curent_user.id
I thing you should put an # in front of your current_user to make it accessible in the ERB and in the controller.
Plus, once you save the current_user, you should user params[:user_id] to match the erb (input name is user_id).
Please look at the rails server output, it will tell you what parameters are submitted in the request.
Thanks #jackhaskeyboard. I spelled "current" wrong.
I'm now getting the following errors: Add Favorite Error Messages
1. "User has already been taken"
-A user should be able to post unlimited favorites, so I"m not sure why this is occurring.
"Dishing can't be blank"
-The purpose of this form is to select two variables (dish & restaurant), search the dishing join table to see if that combination exists. If not, create one, if so, grab the dishing_id, and use it to create a new favorite entry (user & dish/restaurant)
Here's my view code:
<div class="row">
<div class="col-md-12">
<form action="/create_favorite" method="post">
<!-- Hidden input for authenticity token to protect from forgery -->
<input name="authenticity_token" type="hidden" value="<%= form_authenticity_token %>">
<!-- Label and input for user_id -->
<div class="form-group">
<% current_user.id %>
<input type="hidden" name="user_id" value="<%= current_user.id%>">
</div>
<!-- Label and input for dishing_id -->
<div class="form-group">
<label for="dishing_id" class="control-label">
Dish
</label>
<%= select_tag(:dish_id, options_from_collection_for_select(Dish.all, 'id', 'dish_name')) %>
</div>
<!-- Label and input for restaurant_id -->
<div class="form-group">
<label for="restaurant_id" class="control-label">
Restaurant
</label>
<%= select_tag(:restaurant_id, options_from_collection_for_select(Restaurant.all, 'id', 'name') ) %>
</div>
<button class="btn btn-success">
Create Favorite
</button>
or
Cancel
</form>
</div>
</div>

Unauthorize error on password update Devise

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

I have a customized form but whatever written on the form is not saved in database

I have a form that uses styles of twitter/bootstrap
however the content of the form is not saved.
May I please know what am I missing?
<%= form_for #customer_detail, url: { action: "create" } do |f| %>
<div class="form-group">
<div class="row">
<div class='col-sm-3'>
<label for="Check in">Check in:</label><br>
<div class='input-group date' id='datetimepicker1'>
<input class="form-control" type='text'>
<span class="input-group-addon"><span class=
"glyphicon glyphicon-calendar"></span></span>
</div>
</div><label for="Check out">Check out:</label><br>
<div class='col-sm-3'>
<div class='input-group date' id='datetimepicker2'>
<input class="form-control" type='text'>
<span class="input-group-addon"><span class=
"glyphicon glyphicon-calendar"></span></span>
</div>
</div>
</div>
<% end %>
Seems like you should read this article. It describe to create form use Rails helpers and action for save to database.

Resources