In the script I wrote, I'm logging into Amazon successfully on behalf of the user with their credentials. Then I'm trying to fill out the form to enter a new address. Here's my current code:
class AmazonCrawler
def initialize
#agent = Mechanize.new do |agent|
agent.user_agent_alias = 'Mac Safari'
agent.follow_meta_refresh = true
agent.redirect_ok = true
end
end
def login
login_url = "https://www.amazon.com/gp/css/account/address/view.html?ie=UTF8&ref_=ya_add_address&viewID=newAddress"
#agent.get(login_url)
form = #agent.page.forms.first
form.email = "whatever#gmail.com"
form.radiobuttons.last.check
form.password = "my_password"
dashboard = #agent.submit(form)
end
end
class UsersController < ApplicationController
def index
response = AmazonCrawler.new.login
form = response.forms[1]
# fill out form
form.enterAddressFullName == "Your Name"
form.enterAddressAddressLine1 = "123 Main Street"
form.enterAddressAddressLine2 = "Apartment 34"
form.enterAddressCity = "San Francisco"
form.enterAddressStateOrRegion = "CA"
form.enterAddressPostalCode = "94101"
form.enterAddressPhoneNumber = "415-555-1212"
form.AddressType = "RES"
form.enterAddressIsDomestic = "0"
form.GateCode = ""
new_response = form.submit( form.button_with(value: /Save.*Continue/) )
end
end
I submit the form and it takes me to the same "Add an Address" form but there are no discernible errors, nothing new on the page. The new_response request has the same form filled out.
When I inspect the post request, here's what I get:
enterAddressFullName=test+user&enterAddressAddressLine1=123+Main+Street&enterAddressAddressLine2=123&enterAddressCity=san+francisco&enterAddressStateOrRegion=ca&enterAddressPostalCode=94101&enterAddressCountryCode=US&enterAddressPhoneNumber=4155551212&enterAddressIsDomestic=0&AddressType=RES&GateCode=&isDomestic=0&newAddress.x=55&newAddress.y=17&newAddress=Save+%26+Continue&addressID=&sessionId=204-4423391-1593712
The main thing that stands out to me is the last part of it:
&newAddress.x=55&newAddress.y=17&newAddress=Save+%26+Continue&addressID=&sessionId=176-3067966-1293712
I'm not setting newAddress.x or newAddress.y anywhere, I seem to be unable to.
Any ideas as to why this isn't submitting successfully? Is it an SSL issue perhaps?
newAddress is the name of the button. The .x and .y indicate where exactly on the button was clicked. There's a lot of reasons why a form will return you back, most likely it didn't like one of your values.
Figured it out. I was setting the name with the == rather than = which was causing the field to be empty
Related
I have implemented user provisioning/deprovisioning with SCIM like so :
users_controller.rb
class Scim::UsersController < Scim::ScimController
before_action :set_scim_provider
def index
startIndex = params[:startIndex].to_i
startIndex = 1 if startIndex < 1# if the user send a startIndex < 1, it is bad data, we don't take it.
itemsPerPage = params[:count].to_i
if itemsPerPage < 1 || itemsPerPage > #scim_provider.max_results
itemsPerPage = #scim_provider.default_number_of_results
end
scim_users = #scim_provider.identity_provider.communaute_accesses.from_scim
if params["filter"]
parser = Scim::QueryFilter::Parser.new
rpn_array = parser.parse(params["filter"])
tree = parser.tree
if tree.length == 3 and tree[0]== 'eq' and tree[1] == 'userName'
userName = tree[2]
scim_users = scim_users.where(provider_identifier: userName.delete('"'))
else
fail 'e'
end
end
paginated_users = scim_users.order(:created_at).offset(startIndex - 1).limit(itemsPerPage)
r = {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": scim_users.size,
"Resources": paginated_users.map { |ca| #scim_provider.representation_for_user(ca) },
"startIndex": startIndex,
"itemsPerPage": itemsPerPage
}
render_json_result(r, 200)
end
def create
if #scim_provider.identity_provider.communaute_accesses.from_scim.find_by(provider_identifier: #body_params['userName'])
render_409_conflict("uniqueness")
else
ca = #scim_provider.identity_provider.communaute_accesses.find_by(provider_identifier: #body_params['userName'], communaute_id: #scim_provider.identity_provider.communaute.id)
if ca.nil?
ca = #scim_provider.identity_provider.communaute_accesses.create(provider_identifier: #body_params['userName'], communaute_id: #scim_provider.identity_provider.communaute.id)
end
ca.update_last_raw_value("scim", #body_string)
ca.extract_values_from_scim
ca.queue_send
end
render_json_result(#scim_provider.representation_for_user(ca), 201)
end
def show
user = #scim_provider.identity_provider.communaute_accesses.from_scim.find_by(provider_identifier: #body_params['userName'])
if user
render_json_result(#scim_provider.representation_for_user(user), 200)
else
render_404_not_found(params[:id])
end
end
def update
ca = #scim_provider.identity_provider.communaute_accesses.from_scim.find_by(provider_identifier: #body_params['userName'])
uc = UserCommunaute.find_by(provider_identifier: #body_params['userName'])
ca.update_last_raw_value("scim", #body_string)
ca.extract_values_from_scim
unless ca.nil?
if ca.pending?
ca.update_last_raw_value("scim", #body_string)
ca.update(active: false)
if ca.active == false
fail "Unable to delete this user because of activeness" if ca.active == true
ca.destroy!
end
render_json_result(#scim_provider.representation_for_communaute_access_patch(ca), 200)
end
end
unless uc.nil?
uc.update(active: #body_params['active'])
if uc.active == false
uc.user.communaute_accesses.from_scim.destroy_all
uc.user.user_communautes.from_scim.destroy_all
render_json_result(#scim_provider.representation_for_user_communaute_patch(uc), 200)
end
end
end
end
Explanations:
When updating a user, SCIM sends a PATCH request like this:
{"schemas"=>["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations"=>[{"op"=>"Replace", "path"=>"active", "value"=>"False"}]} (#body_params in the code)
Which is what i am expecting. But, for a while, i was receiving the userName also in the body response during the PATCH operation.
This is how I fetch the correct user in my DB.
Actual result:
I don't receive the userName anymore when SCIM hits my update action.
Expected results:
Being able to receive information about the user during the PATCH operation to fetch the userName and find the right user in my database.
I have tried almost everything. When SCIM hits the index action, which it does everytime before going anywhere else, it does return me a userName et everything ends up as a 200 OK.
Then, when passing through update, it sends me nothing.
What I have tried last is to isolate the userName as an instance variable in the index action to fetch it after in the update like so:
# index
...
if params["filter"]
parser = Scim::QueryFilter::Parser.new
rpn_array = parser.parse(params["filter"])
tree = parser.tree
if tree.length == 3 and tree[0]== 'eq' and tree[1] == 'userName'
#user_name = tree[2]
scim_users = scim_users.where(provider_identifier: #user_name.delete('"'))
else
fail 'e'
end
end
...
# update
def update
ca = #scim_provider.identity_provider.communaute_accesses.from_scim.find_by(provider_identifier: #user_name)
uc = UserCommunaute.find_by(provider_identifier: #user_name)
ca.update_last_raw_value("scim", #body_string)
ca.extract_values_from_scim
...
But, #user_name in update seems to disappear as its value is nil.
I am deprovisioning from Azure Active Directory and Okta in a production environment.
Mapping is ok in both platforms.
Provisioning is working like a charm.
Please refer to https://developer.okta.com/docs/reference/scim/scim-20/#update-a-specific-user-patch for PATCH /Users/{userId}. Could you not make use of the userId in the url to identify the user ?
So I'm trying to send a contact us form into dropbox, so the goal is for a user to create a lead (contact us form) with an upload_file field (attachment) and then I'm going to ask that user if he wants to become a customer irl, so if he becomes one, I want that attachment in his lead (contact us form related to him) to go into my dropbox.
so here is my contact us controller:
class LeadsController < ApplicationController
require 'dropbox_api'
skip_before_action :verify_authenticity_token
def create
#lead = Lead.new
fullname = params['Name']
company = params['Company']
email = params['Email']
phone = params['Phone']
projectName = params['ProjectName']
projectDescription = params['ProjectDescription']
department_incharge = params['DepartmentInCharge']
message = params['Message']
attachment = params['attachment']
#lead.full_name = fullname
#lead.company_name = company
#lead.email = email
#lead.phone = phone
#lead.project_name = projectName
#lead.project_description = projectDescription
#lead.department_in_charge = department_incharge
#lead.message = message
params_attach = attachment
if params_attach
#lead.attachment = params_attach.read
#lead.original_filename = params_attach.original_filename
client = DropboxApi::Client.new(ENV['DROPBOX_OAUTH_BEARER'])
#lead.save!
redirect_to root_path
end
end
end
here is my customer model:
class Customer < ApplicationRecord
has_many :lead
has_many :buildings
belongs_to :address
belongs_to :user
after_update :dropbox
self.all.each do |lead|
def dropbox
self.lead.all.each do |lead|
if lead.attachment != nil
client = DropboxApi::Client.new(ENV['DROPBOX_OAUTH_BEARER'])
client.create_folder("/#{lead.full_name}")
client.upload("/#{lead.full_name}/#{File.basename(lead.original_filename)}", lead.attachment)
# lead.file_attachment = nil
# lead.original_filename = nil
# lead.save!
end
end
end
end
end
The problem is when i hit the send button to confirm my quote, it just refreshes the page (it's supposed to go to a confirmation page) and in the ubuntu console, this appears:
No template found for LeadsController#create, rendering head :no_content
Completed 204 No Content in 795ms (ActiveRecord: 0.0ms)
Tell me if you need any more information, I'm really stuck on that one
Try this, move redirect_to out of if, add flash message to make it more clear, I suspect params_attach is false/nil in this case
if params_attach
#lead.attachment = params_attach.read
#lead.original_filename = params_attach.original_filename
client = DropboxApi::Client.new(ENV['DROPBOX_OAUTH_BEARER'])
#lead.save!
end
redirect_to root_path
Hope that helps!
I have a model with an initializer in it, which basically creates a user from a user hash.
After it gets the user information, it checks whether the "privileges" key in the hash is an array. If it's not, it turns it into an array.
Now the obvious way of doing this would be crafting an entire user_hash so that it would skip those "create user" lines and then check if it turns the input into an array if necessary. However, I was wondering if there is a more DRY way of doing this?
Here is the user model I'm talking about:
def initialize(opts={})
#first_name = opts[:user_hash][:first]
#last_name = opts[:user_hash][:last]
#user_name = opts[:user_hash][:user_name]
#email = opts[:user_hash][:email]
#user_id = opts[:user_hash][:id]
#privileges = {}
if opts[:privs].present?
if !opts[:privs].kind_of?(Array)
opts[:privs] = [opts[:privs]]
end
end
end
You can pass a double which returns the needed value when the proper key is requested, and itself (or something else) otherwise:
it 'turns privs into an array' do
opts = double(:opts)
allow(opts)to receive(:[]).and_return(opts)
allow(opts)to receive(:[]).with(:privs).and_return('not array')
expect(MyClass.new(opts).privileges).to eq(['not array'])
end
Btw, your code could be simplified using the splat operator:
privs = [*opts[:privs]]
sample behavior:
privs = nil
[*privs]
# => []
privs = ['my', 'array']
[*privs]
# => ["my", "array"]
privs = 'my array'
[*privs]
# => ["my array"]
You can even use the idempotent Kernel#Array
def initialize(opts = {})
#first_name = opts[:user_hash][:first]
#last_name = opts[:user_hash][:last]
#user_name = opts[:user_hash][:user_name]
#email = opts[:user_hash][:email]
#user_id = opts[:user_hash][:id]
#privileges = {}
Array(opts[:privs])
end
I hope that helps
Rather than testing the implementation (value is turned into an array), I would test the desired behavior (takes single privilege or multiple privileges):
describe User do
describe '#initialize' do
it "takes single privilege" do
user = User.new(user_hash: {}, privs: 'foo')
expect(user.privileges).to eq(['foo'])
end
it "takes multiple privileges" do
user = User.new(user_hash: {}, privs: ['foo', 'bar'])
expect(user.privileges).to eq(['foo', 'bar'])
end
end
end
I am developing a Rails application and want to put some info that I already read from an XML file and show it in a new page.
In my view I have:
<%= link_to 'Hoteles', :method => :hotels %>
and the controller method is:
def hotels
url = "http://api.hotelsbase.org/search.php?longitude="+#city_visit.longitude+"&latitude="+#city_visit.latitude
data = Nokogiri::HTML(open(url))
$name = data.xpath("//name")
$fulladdress = data.xpath("//fulladdress")
$phone = data.xpath("//phone")
$city = data.xpath("//city")
$description = data.xpath("//description")
$featured = data.xpath("//featured")
$stars = data.xpath("//stars")
$rating = data.xpath("//rating")
$long = data.xpath("//long")
$lat = data.xpath("//lat")
$dist = data.xpath("//dist")
$price = data.xpath("//price")
$tripadvisorurl = data.xpath("//tripadvisorurl")
$url = data.xpath("//url")
$hotelsbaseUrl = data.xpath("//hotelsbaseUrl")
end
Now I want to show that information in a HTML page.
All the global variables (starting with a $) you've defined should be instance variables (starting with an #)
#name = data.xpath("//name")
#fulladdress = data.xpath("//fulladdress")
And then you can use them in the hotels.html.erb view, like this
<%= #name %>
You should look at Rails guides to find more information and good practices about Rails; the one called "Layouts and Rendering in Rails" would have helped you for this question.
How can i apply validation in admin on various fields when they are dependent on each other ?
e.g. Let say in i have a Field A(BooleanField) and Field B (CharField) what i want to do is if in admin user select the Field A(checkbox) and does not enter anything in Field B
and if he tries to save ,it should throw an error like a normal blank=False gives. So how can i do this kind of validation in admin .
E.g Use Case
I have a table having the following structure :-
INTERVIEW_TYPES = (
('default', 'None'),
('Paired Visit','Paired Visit'),
('Time Series', 'Time Series'),
),
class Interview(models.Model):
ic_number = models.CharField(verbose_name ="Visit Configuration Number",max_length=20,unique=True,null =True,blank=True)
ic_description = models.TextField(verbose_name ="Visit Configuration Description",null = True,blank=True)
title = models.CharField(verbose_name ="Visit Configuration Title",max_length=80,unique=True)
starting_section = models.ForeignKey(Section)
interview_type = models.CharField(verbose_name = "Mapped Visit",choices=CHOICES.INTERVIEW_TYPES, max_length=80, default="Time Series")
select_rating = models.CharField(choices=CHOICES.QUESTION_RATING, max_length=80, default="Select Rating")
view_notes = models.CharField(choices=CHOICES.VIEW_NOTES, max_length=80, default="Display Notes")
revisit = models.BooleanField(default=False)
.....and so on ......
class Meta:
verbose_name = 'Visit Configuration'
verbose_name_plural = 'Visit Configurations'
# ordering = ('rpn_number',)
def __unicode__(self):
return self.title
Its admin.py
class InterviewAdmin(admin.ModelAdmin):
list_display = ('id','title', 'starting_section','ic_number','show_prior_responses')
raw_id_fields = ('starting_section',)
admin.site.register(Interview, InterviewAdmin)
In admin , If i select the checkbox of revisit and in the field interview_type(which will show a dropdown having choices None,Paired Visit , Time Series) if a User has selected None from that dropdown and then press save button it should throw me an error like a normal blank=False shows, saying "This field is required"
How can i do this kind validation where fields are dependent on each other ?
Please Ignore syntax error is any .
Thanks
I got confused in response_change and overriding clean method finally this is what i did
override clean method by making a model form in admin.py
class InterviewAdminForm(forms.ModelForm):
class Meta:
model = Interview
def clean(self, *args, **kwargs):
cleaned_data = super(InterviewAdminForm, self).clean(*args, **kwargs)
if self.cleaned_data['interview_type'] == "default" \
and self.cleaned_data['Revisit'] == True:
raise forms.ValidationError({'interview_type': ["error message",]})
return cleaned_data
class InterviewAdmin(admin.ModelAdmin):
# call the form for Validation
form = InterviewAdminForm
#....and so on ....