send delete request to controller in cucumber step definition - ruby-on-rails-3

Does any of you know how to do (implement) something like this:
sample.feature
...
scenario: unauthorized user cannot delete event
Given list of events
When event is deleted
Then nothing happen
...
sample_steps.rb
...
When /^event is deleted$/ do
delete (_path_to_controller_ + "/%d" % #events.first().id)
...
Of course in this step I want to send a request according to the result of rake routes, which is something like this (I've moved resources under admin path):
rake routes
...
DELETE /admin/controller_name/:id(.:format) controller_name#destroy
...
I have been experimenting and searching internet for so long and yet I don't know how to do it :(

I've used Rack::Test in the past to send DELETE requests to an API:
When /^event is deleted$/ do
header 'Accept', 'application/json'
header 'Content-Type', 'application/json'
authorize "username", "password"
url = _path_to_controller_ + "/%d" % #events.first().id)
delete url
end
Having said that, I'm not sure I'd recommend it in your case. Is the event going to be deleted from some action in the interface such as clicking a button? If so, you should use capybara to log in and click the button. This gives you the benefit of full integration coverage and you don't have to deal with Rack::Test (not that it's a bad tool, but it's another tool).

Uff I've solved the problem.
Great Thanks to Beerlington
So in this post I will sum up my time with the problem and its solution.
Related topics and documentation
StackOverflow: HTTP basic auth for Capybara
Devise: How To: Use HTTP Basic Authentication
Background
I'm using devise gem for authentication. My goal was to check if possible is manual hacking to resource management features like delete.
Problem
Above ;D
Solution
When /^event is deleted$/ do
header 'Accept', 'application/json'
header 'Content-Type', 'application/json'
authorize "username", "password"
url = _path_to_controller_ + "/%d" % #events.first().id)
delete url
end
is not working with default devise configuration. Because it uses HTTP authentication which is disabled by default.
config/initializers/devise.rb
# Tell if authentication through HTTP Basic Auth is enabled. False by default.
# It can be set to an array that will enable http authentication only for the
# given strategies, for example, `config.http_authenticatable = [:token]` will
# enable it only for token authentication.
# config.http_authenticatable = false
So if we want to make above test working, we need to change last line to:
config.http_authenticatable = true
But the question is do we really wanna do it ?
And as a last note: header calls are optional. Records are deleted with or without them.
with them delete return with status code : 204 No Content
and without them delete return with status code : 302 Found

Related

In karate mocking (karate-netty), how can we override request header value?

Objective:
We want few API calls should go to mock-server(https://192.x.x.x:8001) and others should go to an actual downstream application server(https://dev.api.acme.com).
Setup :
On local, mock server is up with standalone jar on port 8001. e.g https://192.x.x.x:8001
In application config file (config.property)downstream system(which need to mock) defined with mockserver IP i.e https://192.x.x.x:8001
Testing scenario and problem:
1.
Scenario: pathMatches('/profile/v1/users/{id}/user')
* karate.proceed('https://dev.api.acme.com')
* def response = read ('findScope.json')
* def responseStatus = 200ˀˀ
* print 'created response is: ' + response
Now, when we hit API request via postman or feature file then it does karate.proceed properly to https://dev.api.acme.com/profile/v1/users/123/user instead of 192.x.x.x. However, in this request, host is referring to https://192.x.x.x:8001 instead of https://dev.api.acme.com which create a problem for us.
How can we override request header in this case? I did try with karate.set and also with header host=https://192.x.x.x:8001 but no luck.
Thanks!
Please see if the 1.0 version works: https://github.com/intuit/karate/wiki/1.0-upgrade-guide
Unfortunately https proxying may not work as mentioned. If you are depending on this, we may need your help (code contribution) to get this working
If the Host header is still not mutable, that also can be considered a feature request, and here also I'd request you to consider contributing code

how to figure out how to authenticate myself using http requests

I am trying to log in to a site using requests as follows:
s = requests.Session()
login_data = {"userName":"username", "password":"pass", "loginPath":"/d2l/login"}
resp = requests.post("https://d2l.pima.edu/d2l/login?login=1", login_data)
although I am getting a 200 response, when I say
print(resp.content)
b"<!DOCTYPE html><html><head><meta charset='utf-8' /><script>var hash = window.location.hash;if( hash ) hash = '%23' + hash.substring( 1 );window.location.replace('/d2l/login?sessionExpired=0&target=%2fd2l%2ferror%2f404%2flog%3ftargetUrl%3dhttp%253A%252F%252Fd2l.pima.edu%253A80%252Fd2l%252Flogin%253Flogin%253D1' + hash );</script><title></title></head><body></body></html>"
notice it says session expired.
What I've tried:
logging back out and in in the actual browser, no success.
http basic auth, no success.
I'm thinking maybe I need to authenticate myself to this site using cookies?
If so how do I determine which cookies to send it?
I tried figuring this out by saying
resp.cookies
Out[4]: <RequestsCookieJar[]>
shouldn't this be giving me names of cookies? I'm not sure what to do with such output.
Main Point: HOW DO I FIGURE OUT HOW TO AUTHENTICATE MYSLEF TO THIS WEBSITE?
Help is appreciated.
I would rather not use selenium.
From loading this page https://d2l.pima.edu/d2l/login and viewing its source, you'll notice the POST target path is /d2l/lp/auth/login/login.d2l. Try using that as your POST path. Your other fields look consistent with the form's expectations.
Note: with python requests if you create a session object use it to make your requests:
resp = s.post(<blah blah>, login_data)
The session will hold any cookies set by the login server, and you can continue to use the s object to make requests in the authenticated session.

intermittent error from rally 'Not authorized to perform action: Invalid key' for POST request in chrome extension

I developed a chrome extension using Rally's WSAPI v2.0, and it basically does the following things:
get user and project, and store them
get current iteration everytime
send a post request to create a workitem
For the THIRD step, I sometimes get error ["Not authorized to perform action: Invalid key"] since end of last month.
[updated]Error can be reproduced everytime if I log in Rally website via SSO before using the extension to send requests via apikey.
What's the best practice to send subsequent requests via apikey in my extension since I can't control end users' habits?
I did see some similar posts but none of them is helpful... and in case it helps:
I'm adding ZSESSIONID:apikey in my request header, instead of user /
password to authenticate, so I believe no security token is needed
(https://comm.support.ca.com/kb/api-key-and-oauth-client-faq/kb000011568)
url starts with https://rally1.rallydev.com/slm/webservice/v2.0/
issue is fixed after clearing cookies for
https://rally1.rallydev.com/, but somehow it appears again some time
later
I checked the cookie when the issue was reproduced, and found one with name of ZSESSIONID and its value became something else rather than the apikey. Not sure if that matters though...
code for request:
function initXHR(method, url, apikey, cbFunc) {
let httpRequest = new XMLHttpRequest();
...
httpRequest.open(method, url);
httpRequest.setRequestHeader('Content-Type', ' application\/json');
httpRequest.setRequestHeader('Accept', ' application\/json');
httpRequest.setRequestHeader('ZSESSIONID', apikey);
httpRequest.onreadystatechange = function() {
...
};
return httpRequest;
}
...
usReq = initXHR ('POST', baseURL+'hierarchicalrequirement/create', apikey, function(){...});
Anyone has any idea / suggestion? Thanks a million!
I've seen this error when the API key had both read-only and full-access grants configured. I would start by making sure your key only has the full-access grant.

How do I create header from other header values in Traefik

In Traefik, I want to take the values of headers that come from a forwarded auth, and add them to the ongoing request as a combined custom header.
I see that I can simply forward the headers using:
authResponseHeaders = ["X-Auth-Token", "X-Token-Type"]
What I really need to achieve is to combine these into another header (pseudo code):
Authorization = X-Token-Type + " " + X-Auth-Token
Our ongoing request needs to authenticate using the Authorixation header, but this would be incorrect unless (I think, I can't test this right now) I pass Authorization back from my forwarded auth, and use:
authResponseHeaders = ["Authorization"]
Caveat, I haven't tested the above as Traefik got deleted until I can prove it will work. Sad I know.
Is any of this rambling question possible?

speedy_c2dm: NoMethodError (undefined method `gsub' for nil:NilClass)

I set up speedy_c2dm to send "push" messages to android devices.
The gem was working fine, but now I get this NoMethodError message when I call
SpeedyC2DM::API.send_notification(options)
the options parameter is good, I have verified this.
From the ruby-doc I got the following code from the gem:
def get_auth_token(email, password)
data = "accountType=HOSTED_OR_GOOGLE&Email=#{email}&Passwd=#{password}&service=ac2dm"
headers = { "Content-type" => "application/x-www-form-urlencoded",
"Content-length" => "#{data.length}"}
uri = URI.parse(AUTH_URL)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response, body = http.post(uri.path, data, headers)
return body.split("\n")[2].gsub("Auth=", "")
end
You can see that the last line uses gsub, so I believe the problem is in the authentication method.
I have changed the password of the account since I created this, I updated the file with the password, initializers/speedy_c2dm.rb:
C2DM_API_EMAIL = "myemail#gmail.com"
C2DM_API_PASSWORD = "mynewpassword"
SpeedyC2DM::API.set_account(C2DM_API_EMAIL, C2DM_API_PASSWORD)
Can this be causing the error? That I changed the password even though I updated this file?
(Google doesn't let me to go back to the old password, I have to create a new one different from the old ones if I change it again)
Its the only thing I can think of since I didn't modify the gem's code.
How can I fix it? C2DM is deprecated now, but its supposed to keep working for old users. I don't want to migrate to GCM if I don't need to, everything is set up to work with C2DM
Any other ideas to fix it are welcome.
The problem was fixed after I removed the "two step verification" for logging in to my email.
This change can be made in the account configuration of gmail.