How does one pull an API environment variable in rails - ruby-on-rails

Implementing in rails and only running locally for the time being.
Using I have a google API server key for google places that is... lets say... "abc123"
When I use a url just to see with a url like:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&sensor=false&key=abc123
it pulls information.
When I type env from mac terminal I have a value listed that is :
PLACES_API=abc123
when I run the code filling in the literal key:
#client = GooglePlaces::Client.new("abc123")
it works fine.
HOWEVER, when I try and pull this in using
#client = GooglePlaces::Client.new(ENV['PLACES_API'])
it errors out and when I try to puts ENV['PLACES_API'] it is blank.
I am assuming I am not using the env variable correctly, but now I want to know what I am doing wrong and how to use the environmental variable.

OPTION 1
If you are using ENV['PLACES_API'] in your code then before you start rails server you have to export the key. In your terminal run export PLACES_API="api key" and then start the server.
OPTION 2 (A better way to handle secret keys )
create a file gmap.yaml inside config directory with the following code
development:
secret: "api key"
test:
secret: "api key"
production:
secret: "api key"
Now create a new file gmap.rb inside config/initializars directory with the following code
PLACES_API = YAML.load_file("#{::Rails.root}/config/gmap.yml")[::Rails.env]
Now you can access the key with
#client = GooglePlaces::Client.new(PLACES_API['secret'])

Related

How to access AWS Comprehend using aws-sdk-comprehend gem?

I'm working on getting my Rails app interacting with the AWS Comprehend service for text entity extraction. I'm using the aws-sdk-comprehend gem. I have successfully gotten my app working with the AWS Rekognition service for image analysis using the aws-sdk-rekognition gem.
I can't seem to get the AWS Comprehend authentication correct as all of my calls result in an Aws::Comprehend::Errors::InvalidRequestException.
I have all of the following ENV variables set:
AWSAccessKeyId
AWSSecretKey
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
My code looks something like this:
class MyApp::Aws::ComprehendService < MyApp::ServiceBase
def call
#credentials = Aws::Credentials.new(ENV['AWSAccessKeyId'], ENV['AWSSecretKey'])
#client = Aws::Comprehend::Client.new(region: "us-west-1", credentials: credentials)
#client.detect_entities({text: "this is a simply little blob of text", language_code: "en"})
end
end
This resulted in Aws::Comprehend::Errors::InvalidRequestException. So I also tried:
class MyApp::Aws::ComprehendService < MyApp::ServiceBase
def call
# use ENV credential format I've seen in examples...
#credentials = Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'])
#client = Aws::Comprehend::Client.new(region: "us-west-1", credentials: credentials)
#client.detect_entities({text: "this is a simply little blob of text", language_code: "en"})
end
end
I found an example that didn't use the #credential approach. The example claimed "The initialize method will load the credentials environment variables by itself". So I tried this:
class MyApp::Aws::ComprehendService < MyApp::ServiceBase
def call
# ignore setting the credentials
#client = Aws::Comprehend::Client.new(region: "us-west-1")
#client.detect_entities({text: "this is a simply little blob of text", language_code: "en"}).
end
end
This also resulted in Aws::Comprehend::Errors::InvalidRequestException.
Can you see anything I'm doing wrong? Has anyone had success in using this gem to interact with the Comprehend API?
Per the Documentation for Aws::Comprehend::Client#detect_entities
If the system detects a document-level error in your input document, the API returns an InvalidRequestException error response. For details about this exception, see Errors in semi-structured documents in the Comprehend Developer Guide.
So it appears your usage is not necessarily the issue but rather the input documents themselves.
The response however should include what the actual issue is according to the Developer Guide:
Document-level errors
If the ClassifyDocument or DetectEntities API operation detects a document-level error in your input document, the API returns an InvalidRequestException error response.
In the error response, the Reason field contains the value INVALID_DOCUMENT.
The Detail field contains one of the following values:
DOCUMENT_SIZE_EXCEEDED – Document size is too large. Check the size of your file and resubmit the request.
UNSUPPORTED_DOC_TYPE – Document type is not supported. Check the file type and resubmit the request.
PAGE_LIMIT_EXCEEDED – Too many pages in the document. Check the number of pages in your file and resubmit the request.
TEXTRACT_ACCESS_DENIED_EXCEPTION – Access denied to Amazon Textract. Verify that your account has permission to use the Amazon Textract DetectDocumentText and AnalyzeDocument API operations and resubmit the request.
The Aws::Comprehend::Errors::InvalidRequestException object is documented so it appears you could potentially figure out what is wrong via
def call
# use ENV credential format I've seen in examples...
#credentials = Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'])
#client = Aws::Comprehend::Client.new(region: "us-west-1", credentials: credentials)
begin
#client.detect_entities({text: "this is a simply little blob of text", language_code: "en"})
rescue Aws::Comprehend::Errors::InvalidRequestException => e
# interrogate the error object here e.g.
puts {reason: e.reason, detail: e.detail}
end
end

Does not have storage.buckets.list access to the Google Cloud project?

I wrote a Ruby script that will upload an audio file to a Google Cloud Storage.
def upload_to_Google_cloud(audio_file)
project_id = "<project_id>"
key_file = "<json_file>"
storage = Google::Cloud::Storage.new project: project_id, keyfile: key_file
bucket_name = storage.buckets.first.name
puts bucket_name
bucket = storage.bucket bucket_name
local_file_path = "/path/#{audio_file}"
file = bucket.create_file local_file_path, "#{audio_file}.flac"
return "Uploaded #{file.name}"
end
Though, everytime I run the command -> ruby video_dictation.rb, it returns me an error which is xxxxxxxxx does not have storage.buckets.list access to the Google Cloud project. (Google::Cloud::PermissionDeniedError).
Any help, suggestions? Thanks!
Should be permission issue.
Try to create a service account. It looks like this "my-storage-bucket#yourprojectname.iam.gserviceaccount.com"
Go to IAM & Admin -> Permission
Assign that service account with "Storage Object Admin" role.
Try your code again. If is working, please scope down your permission to the below list based on your needs.
5. Remember to download the json key file for that particular service account.

Action Mailbox saying "Missing required Mailgun API key" even though key is present

I have Mailgun set up to forward emails to my /rails/action_mailbox/mailgun/inbound_emails/mime endpoint.
When my endpoint receives the request, it gives the following error:
ArgumentError (Missing required Mailgun API key. Set
action_mailbox.mailgun_api_key in your application's encrypted
credentials or provide the MAILGUN_INGRESS_API_KEY environment
variable.)
However, MAILGUN_INGRESS_API_KEY is in fact set. When I run ENV["MAILGUN_INGRESS_API_KEY"] in the console, I see my API key. I even pasted in the API key determination code from GitHub to see if there was a problem there, but the return value I got was my actual API key.
Any ideas on what the problem could be?
Just checking few things to see if can rectify, as I understand you know much better than me about rails.
Do you have setup mailgun api_key in environment configuration like for development config/environments/development.rb
config.action_mailer.delivery_method = :mailgun
config.action_mailer.mailgun_settings = {
api_key: ENV['MAILGUN_INGRESS_API_KEY'],
domain: 'your_domain.com',
# api_host: 'api.eu.mailgun.net' # Uncomment this line for EU region domains
}
Now let us do one test, visit (bin.mailgun.net) and get paste bin url then run rails c
mg_client = Mailgun::Client.new(ENV["MAILGUN_INGRESS_API_KEY"], "bin.mailgun.net", "aecf68de_you_got_visiting_site", ssl = false)
message_params = { from: 'bob#sending_domain.com',
to: 'sally#example.com',
subject: 'The Ruby SDK is awesome!',
text: 'It is really easy to send a message!'
}
result = mg_client.send_message("your_sending_setup_on_mailgun_domain.com", message_params)
puts result.inspect
See what message came and you may get idea. There could be environment configuration issue also for development you have to setup different then for production. Also check on paste-bin does it got any hit.

How to Authenticate Google Vision/Cloud Using ENV Variable in Ruby on Rails

My app is hosted on Heroku, so I'm trying to figure out how to use the JSON Google Cloud provides (to authenticate) as an environment variable, but so far I can't get authenticated.
I've searched Google and Stack Overflow and the best leads I found were:
Google Vision API authentication on heroku
How to upload a json file with secret keys to Heroku
Both say they were able to get it to work, but they don't provide code that I've been able to get work. Can someone please help me? I know it's probably something stupid.
I'm currently just trying to test the service in my product model leveraging this sample code from Google. Mine looks like this:
def self.google_vision_labels
# Imports the Google Cloud client library
require "google/cloud/vision"
# Your Google Cloud Platform project ID
project_id = "foo"
# Instantiates a client
vision = Google::Cloud::Vision.new project: project_id
# The name of the image file to annotate
file_name = "http://images5.fanpop.com/image/photos/27800000/FOOTBALL-god-sport-27863176-2272-1704.jpg"
# Performs label detection on the image file
labels = vision.image(file_name).labels
puts "Labels:"
labels.each do |label|
puts label.description
end
end
I keep receiving this error,
RuntimeError: Could not load the default credentials. Browse to
https://developers.google.com/accounts/docs/application-default-credentials for more information
Based on what I've read, I tried placing the JSON contents in secrets.yml (I'm using the Figaro gem) and then referring to it in a Google.yml file based on the answer in this SO question.
In application.yml, I put (I overwrote some contents in this post for security):
GOOGLE_APPLICATION_CREDENTIALS: {
"type": "service_account",
"project_id": "my_project",
"private_key_id": "2662293c6fca2f0ba784dca1b900acf51c59ee73",
"private_key": "-----BEGIN PRIVATE KEY-----\n #keycontents \n-----END PRIVATE KEY-----\n",
"client_email": "foo-labels#foo.iam.gserviceaccount.com",
"client_id": "100",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url":
"https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url":
"https://www.googleapis.com/robot/v1/metadata/x509/get-product-labels%40foo.iam.gserviceaccount.com"
}
and in config/google.yml, I put:
GOOGLE_APPLICATION_CREDENTIALS = ENV["GOOGLE_APPLICATION_CREDENTIALS"]
also, tried:
GOOGLE_APPLICATION_CREDENTIALS: ENV["GOOGLE_APPLICATION_CREDENTIALS"]
I have also tried changing these variable names in both files instead of GOOGLE_APPLICATION_CREDENTIALS with GOOGLE_CLOUD_KEYFILE_JSON and VISION_KEYFILE_JSON based on this Google page.
Can someone please, please help me understand what I'm doing wrong in referencing/creating the environmental variable with the JSON credentials? Thank you!
It's really annoying that Google decides to buck defacto credential standards by storing secrets via a file instead of a series of environment variables.
That said, my solution to this problem is to create a single .env variable GOOGLE_API_CREDS.
I paste the raw JSON blob into the .env then remove all newlines. Then in the application code I use JSON.parse(ENV.fetch('GOOGLE_API_CREDS') to convert the JSON blob into a real hash:
The .env file:
GOOGLE_API_CREDS={"type": "service_account","project_id": "your_app_name", ... }
Then in the application code (Google OCR client as an example):
Google::Cloud::Vision::ImageAnnotator.new(credentials: JSON.parse(ENV.fetch('GOOGLE_API_CREDS'))
Cheers
Building on Dylan's answer, I found that I needed to use an extra line to configure the credentials as follows:
Google::Cloud::Language.configure {|gcl| gcl.credentials = JSON.parse(ENV['GOOGLE_APP_CREDS'])}
because the .new(credentials: ...) method was not working for Google::Cloud::Language
had to look in the (sparse) ruby reference section of Google Cloud Language.
And yeah... storing secrets in a file is quite annoying, indeed.
I had the same problem with Google Cloud Speech, using the "Getting Started" doc from Google.
The above answers helped a great deal, coupled with updating my Google Speech Gem to V1 (https://googleapis.dev/ruby/google-cloud-speech-v1/latest/Google/Cloud/Speech/V1/Speech/Client.html)
I simply use a StringIO object so that Psych thinks that it's an actual file that I read:
google:
service: GCS
project: ''
bucket: ''
credentials: <%= StringIO.new(ENV['GOOGLE_CREDENTIALS']) %>

Amazon MTurk SDK Ruby gem - RuntimeError: Missing AWSAccessKey

How/where does a rails app specify the MTurk Key & Secret?
The Amazon Mechanical Turk SDK gem docs do not seem to indicate where/how to specify the Access Key and Secret... if you run their sample code in IRB it prompts for the Key and Secret... but where does one specify them in a one-time configuration so an application can run?
For example Amazon gives this code:
require 'mturk'
#mturk = Amazon::WebServices::MechanicalTurkRequester.new
puts "I have $#{#mturk.availableFunds} in Sandbox"
which causes the gem to prompt interactively for the Key and Secret.
Doing this instead:
mturk = Amazon::WebServices::MechanicalTurkRequester.new :AWSAccessKeyId => "xxxx", :AWSSecretAccessKey => "yyyy
gives the error message:
RuntimeError: Missing AWSAccessKey
The key & secret being specified is definitely correct, because I can copy/paste them into the interactive prompt and it works fine.
If this is documented anywhere I fail to find it, but the answer is that unlike every other AWS library I've used they rename the 'secret' to :AWSAccessKey
So this works:
mturk = Amazon::WebServices::MechanicalTurkRequester.new :AWSAccessKeyId => "xxxx", : AWSAccessKey => "yyyy

Resources