Ruby: Get currently logged in user on windows - windows

In C# I can get the current user of a web app using the HttpContext, however, I can't figure out how to do this in Ruby. Is there any way of doing this?
FOR THOSE OF YOU SAYING IT IS IMPOSSIBLE, HERES PROOF:
http://www.codeproject.com/KB/aspnet/How_to_NT_User_Name.aspx

Well, to get the current username, there's this:
puts ENV['USERNAME']
Or go to the Win32API.
require 'dl/win32'
def get_user_name
api = Win32API.new(
'advapi32.dll',
'GetUserName',
'PP',
'i'
)
buf = "\0" * 512
len = [512].pack('L')
api.call(buf,len)
buf[0..(len.unpack('L')[0])]
end
puts get_user_name
Edit: And I'm an idiot. This isn't what you asked for at all. Oh well, it took me time to dig this out of my code, so it might as well stay here for anyone else wondering :P
Edit again: OK, it turns out I'm not an idiot after all. This is what you want. When I went back and re-read your question, the HttpContext threw me off, and I thought it was the current username from HTTP auth or something.

To get the username of the current user on client machine you can use this
ENV['USERNAME']

If you're using Rails try: request.env['HTTP_REMOTE_USER']

I think what you mean is how you can retrieve the username that the user used to login to the web application. That will differ depending on what authentication mechanism you're using. Some Apache authentication modules, for example, will pass REMOTE_USER (e.g. the Kerberos module), the CAS Single-Sign-On module passes CAS-USER, etc. Standard digest authentication and such uses the Authentication header. You should be able to access these using request.env[HEADER] as someone else pointed out above. Check out the documentation on how your authentication layer is passing on the user in the HTTP request.

Is your c# code running as a .NET plugin/client-side code or is it ENTIRELY server side? Your ruby code would be entirely server side. According to the MS docs, only stuff running in the CLR sandbox can really get to that information:
http://msdn.microsoft.com/en-us/magazine/cc163700.aspx (under Defining the sandbox).
One thing interesting to note is that sites registered under LocalIntranet have access to that information. I'm not sure off hand how this maps to security zones in IE though.
The thing to understand is that LOGON_USER is NOT visible to the browser sandbox anymore than the browser can see the contents of a filesystem path on your system. The fact that your c# code sees it almost certainly indicitive of some clientside component passing it upstream.
You have the option of implementing mod_ntlm under apache and pushing the headers downstream. I don't have the points to post a second link but google 'rails ntlm sso' and see the rayapps.com link.
but if your app isn't Rails based, you'll have to port that to your server code. You can also checkout rack-ntlm if your app is rack compliant.

[RUBY ON RAILS ONLY]
This is what worked for me but there are some limitations:
won't work in Chrome: undefined method 'encode' for nil:NilClass
won't validate user credentials
If you don't care about these issues, go ahead:
In your rails application, add Rekado's gem to your Gemfile: gem 'ntlm-sso', '=0.0.1'
Create an initialiser config/initializers/ntlm-sso.rb with:
require 'rack'
require 'rack/auth/ntlm-sso'
class NTLMAuthentication
def initialize(app)
#app = app
end
def call(env)
auth = Rack::Auth::NTLMSSO.new(#app)
return auth.call(env)
end
end
On your application.rb file, add the line: config.middleware.use "NTLMAuthentication"
Call request.env["REMOTE_USER"] on your view or controller to get current username.
PS: Let me know if you find anyway to make it work on Chrome or to validate user credentials.

Related

Reading a Google Spreadsheet into Ruby Objects (or settle for a file download)

I think it's probably simplest to start with my use case:
I'm trying to read the contents of a Google Spreadsheet into ruby, and then use that data for other purposes. This needs to happen server-to-server.
Here's what I've tried:
First I tried to use this google drive gem. Since my interaction needs to be server to server (i.e. a service account), I couldn't get this to work (someone please let me know if they've managed this!)
Next, I tried using the latest google-api-ruby gem, and, following its documentation, was successfully able to authenticate my service account, and have been able to get lists of files, etc. So basically the API is authenticated and working.
The latest issue is that Google Spreadsheets can't be downloaded using the normal download_dest parameter on the get_file method (sorry - would post links to relevant documentation here, but don't have enough rep to do so). So I'm not really sure how to proceed with downloading the relevant file (I understand how to get an export_link), but have no clue how to then prepare the next request).
Any help would be greatly appreciated :)
Here's some basic code for reference -
require 'googleauth'
require 'google/apis/drive_v2'
scopes = ['https://www.googleapis.com/auth/drive']
ENV["GOOGLE_APPLICATION_CREDENTIALS"] = 'path/to/my/creds.json'
auth = Google::Auth.get_application_default(scopes)
drive = Google::Apis::DriveV2::DriveService.new
drive.authorization = auth
ss = drive.get_file('my_spreadsheet_id')
export_url = ss.export_links
# what now?

How to enter data for authentication required pop up using ruby, page-object and watir-webdriver

I feel my problem has a simple solution (although I am not able to find a relevant answer through researching). I am using RubyMine ruby 2.0.0 for automated testing and mostly using watir-webdriver, 0.6.4, and page-object, 0.9.4 gems.
When Ruby opens the site I am testing. Before the page loads an Authentication Required pop up box is displayed. It says, "The server http://example.com:80 requires a username and password. The server says: Authentication Required." I am not able to inspect it as an element, therefore I don't know how to interact with it. I have been bypassing the issue by manually entering the username and password.
I think it will be easier to just fill the fields in and click Log In rather then store a cookie, but you guys will know best.
You can pass in the authentication credentials via the URL, which will bypass the dialog. There's an example on http://watirwebdriver.com/basic-browser-authentication/:
require 'watir-webdriver'
b = Watir::Browser.start 'http://admin:password#yourwebsite.com'
b.goto 'https://admin:password#yourwebsite.com/cart' # replace 'cart' as appropriate

How to mock aws-sdk gem?

I have some code that uploads a file to Amazon S3, using the aws-sdk gem. Apparently it does an HTTP put to upload the file.
Is there a good way to mock this functionality of the aws-sdk gem?
I tried using Webmock, but the aws-sdk gem seems to do a get latest/meta-data/iam/security-credentials/ first. It seems that using Webmock may not be the best way to mock this functionality.
Working in RSpec.
If you're using version 2 of the aws-sdk gem try adding:
Aws.config.update(stub_responses: true)
to your RSpec.configure block (usually found in your rails_helper.rb file)
While the above works, it will return empty responses if you don't further specify response content - not necessarily valid, but stubbed.
You can generate and return stubbed response data from a named operation:
s3 = Aws::S3::Client.new
s3.stub_data(:list_buckets)
#=> #<struct Aws::S3::Types::ListBucketsOutput buckets=[], owner=#<struct Aws::S3::Types::Owner display_name="DisplayName", id="ID">>
In addition to generating default stubs, you can provide data to apply to the response stub.
s3.stub_data(:list_buckets, buckets:[{name:'aws-sdk'}])
#=> #<struct Aws::S3::Types::ListBucketsOutput buckets=[#<struct Aws::S3::Types::Bucket name="aws-sdk", creation_date=nil>], owner=#<struct Aws::S3::Types::Owner display_name="DisplayName", id="ID">>
For more details refer to: http://docs.aws.amazon.com/sdkforruby/api/Aws/ClientStubs.html
There are a lot of ways to mock requests in the AWS SDK for Ruby. Trevor Rowe recently posted an article on using the SDK's native support for object stubbing, which does not require any external dependencies like Webmock. You can also use tools like VCR (link will send you to another blog post) to build cacheable integration tests; this way you can test against the live service when you want accuracy and avoid hitting network when you want speed.
Regarding the get request on latest/meta-data/iam/security-credentials/, this happens because the SDK is trying to look up credentials, and, if none are provided, it will check if you are running on an EC2 instance as a last resort, causing the SDK to make an extra HTTP request. You can avoid this check by simply providing bogus static credentials, though if you are using something like VCR, you will want to provide valid credentials for the first run. You can read about how to provide static credentials in another blog post that Trevor wrote on credential management (this should also be in the developer guide and SDK documentation).

Ruby/Cucumber/Capybara Testing Multipart File Uploads

I'm using Cucumber/Capybara to test a web application. I'm pretty much a complete beginner in Ruby and its a real testimony to the developers of Cucumber/Capybara just how far I have been able to test my application with only the miniscule amount of Ruby knowledge that I have.
However, as you've probably guessed, I've reach the point were I need some expert help. I need to test a multipart file upload. The problem is that the web application that I'm testing has a URL command interface, but no associated pages. So I can't just load the page, fill in a parameter and push a button. I have to format the POST command programatically.
Up until now, I have been interacting this the application exclusively using 'visit'. i.e. i have steps definitions such as:
Given /^I delete an alert with alertID "([^"]*)" from the site$/ do |alertID|
visit WEB_SITE_ROOT + "/RemoteService?command=deleteAlert&siteName=#{$Site}&alertID=#{alertID}"
end
But now I need to do some posts. I found some code that seems to do what I need:
Given /^I upload the "([^"]*)" file "([^"]*)" for the alert$/ do |fileType, fileName|
file = File.new(fileName, "rb")
reply = RestClient.post(
"#{WEB_SITE_ROOT}" + "/FileUploader?command=upload&siteName=#{$Site}&alertID=#{$OriginalAlertID}",
:pict => file,
:function => "#{fileType}",
:content_type => 'multipart/jpg',
)
end
But this is not running in the same cucumber/capybara session, and so is not authorised (one of the previous steps was a login). Also, the reply from the web application is not picked up by cucumber/capybara and so my test for success/failure do not work.
Can someone please point me in the right direction?
By default capybara uses the Rack::Test adapter which will bypass the HTTP server and interact with your Rack/your app directly. The POST request you're doing in your step won't go through capybara, hence why it's failing.
To upload files when using Rack::Test you'll need to use the Rails #fixture_file_upload method, which by default should be available in your cucumber steps.

Rack::Test not able to find web app cookie

While testing a Sinatra app with Cucumber, Rack::Test was not able to find the cookie that my app created, even though I could clearly see that it was in the Rack::Test::CookieJar object by dumping it with "p".
I'm answering my own question in order to share the solution with others:
Rack::Test::CookieJar#[] will only return the value of a cookie if it also matches the domain and path. Unfortunately, unless your app's domain is "example.org" you're out of luck.
Fortunately, there's an easy fix: If you're testing with Sinatra, paste the following monkey patch anywhere in your env.rb file in the outermost (global) scope:
module Rack
module Test
DEFAULT_HOST='localhost'
end
end
That's it!

Resources