Rails + Google Calendar API events not created - ruby-on-rails

I created rails web app. When user make some actions, my app must create new event in my Google Calendar. For my task I choose server-to-server authorization.
I wrote next ruby code:
client = Google::APIClient.new({:application_name => "Rails calendar",
:application_version => "1.0"})
keypath = Rails.root.join('config','google_secrets.p12').to_s
key = Google::APIClient::PKCS12.load_key(keypath, "notasecret")
# generate request body for authorization
client.authorization = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:audience => 'https://accounts.google.com/o/oauth2/token',
:scope => 'https://www.googleapis.com/auth/calendar',
:issuer => '***',
:signing_key => key).tap{ |auth| auth.fetch_access_token! }
api_method = client.discovered_api('calendar','v3').events.insert
#meeting_data = {
guests: [{email: '***#gmail.com'}, {email: '***#gmail.com'}],
start_time: "2016-08-10T19:00:00+03:00",
end_time: "2016-08-10T20:00:00+03:00",
topic: "Test meeting",
messages_thread_id: 2
}
event = {
summary: #meeting_data[:topic],
start: {
dateTime: #meeting_data[:start_time],
time_zone: 'Asia/Jerusalem'
},
end: {
dateTime: #meeting_data[:end_time],
time_zone: 'Asia/Jerusalem'
},
attendees: #meeting_data[:guests],
visibility: 'private',
reminders: {
useDefault: true,
}
}
result = client.execute(:api_method => api_method,
:parameters => {calendarId: 'primary'},
:body => JSON.dump(event),
:headers => {'Content-Type' => 'application/json'})
puts result.data.as_json
But when i try to use that code and server return me result as JSON, if I go on url of "created" event, google show me message that event does not exist.
{"kind"=>"calendar#event", "etag"=>"***", "id"=>"***", "status"=>"confirmed", "htmlLink"=>"https://www.google.com/calendar/event?eid=***", "created"=>"2016-08-04T11:54:46.000Z", "updated"=>"2016-08-04T11:54:46.327Z", "summary"=>"Test meeting", "creator"=>{"email"=>"***", "self"=>true}, "organizer"=>{"email"=>"***", "self"=>true}, "start"=>{"dateTime"=>"2016-08-10T16:00:00Z", "timeZone"=>"Asia/Jerusalem"}, "end"=>{"dateTime"=>"2016-08-10T17:00:00Z", "timeZone"=>"Asia/Jerusalem"}, "visibility"=>"private", "iCalUID"=>"***", "sequence"=>0, "attendees"=>[{"email"=>"***#gmail.com", "displayName"=>"***", "responseStatus"=>"needsAction"}, {"email"=>"***#gmail.com", "displayName"=>"***", "responseStatus"=>"needsAction"}], "reminders"=>{"useDefault"=>true}}

I faced with same problem. Needed give write rules to "client_email" for calendar.
You use organization calendar. Thats why only organization admin can do it.

Related

How to delete the attendance check function in Google invitation in Rails?

I'm trying to implement a just notification Google calendar invitation. Currently I'm using Ruby to send a conventional Google Calendar invitation in the service, and it has "yes or no" attendance check button. In order not to attend the meeting, our service customer should indicate their unavailability via the website, but it seems they just clicked no there.
The below is my current code and I think I have to add one or two lines in this code but I'm now sure what that is.
begin
event = {
'summary' => 'Ringle Class',
'description' => 'Ringle Class Notification. Case:' + lesson.course.title,
'start' => {
'dateTime' => lesson.start_time.to_datetime
},
'end' => {
'dateTime' => (lesson.start_time + 1.hour ).to_datetime
},
'attendees' => [
{'email' => lesson.student.email},{'email' => 'xx#xx.com'}
],
}
results = GOOGLE_CAL_CLIENT.execute!(
:api_method => GOOGLE_CAL_API.events.insert,
:parameters => {
:calendarId => GOOGLE_CAL_ID,
'sendNotifications' => true,
'locked' => true,
},
:body_object => event)
lesson.ginv_student = true
lesson.save
$google_invi_log.debug "Sent to the student#{lesson.id}"
rescue
$google_invi_log.debug "Not sent to the student #{lesson.id}"
end
Please share with me any idea you have (:!!
Best

How to resolve "Insufficient Permission" error in Google Calendar API for Ruby?

I'm trying to use Google Calendar API for Ruby and this is code that I took from the google console site. But when I tried to run this code, I got this error.
......rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/google-api-client-0.8.6/lib/google/api_client.rb:662:in `block (2 levels) in execute!': Insufficient Permission (Google::APIClient::ClientError)
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/installed_app'
require 'google/api_client/auth/storage'
require 'google/api_client/auth/storages/file_store'
require 'fileutils'
APPLICATION_NAME = 'Calendar API Quickstart'
CLIENT_SECRETS_PATH = 'client_secret.json'
CREDENTIALS_PATH = File.join(Dir.home, '.credentials',
"calendar-api-quickstart.json")
#SCOPE = 'https://www.googleapis.com/auth/calendar.readonly'
SCOPE = 'https://www.googleapis.com/auth/calendar'
def authorize
FileUtils.mkdir_p(File.dirname(CREDENTIALS_PATH))
file_store = Google::APIClient::FileStore.new(CREDENTIALS_PATH)
storage = Google::APIClient::Storage.new(file_store)
auth = storage.authorize
if auth.nil? || (auth.expired? && auth.refresh_token.nil?)
app_info = Google::APIClient::ClientSecrets.load(CLIENT_SECRETS_PATH)
flow = Google::APIClient::InstalledAppFlow.new({
:client_id => app_info.client_id,
# :redirect_uri => 'http://localhost:3000/auth/google_oauth2/callback',
:client_secret => app_info.client_secret,
:scope => SCOPE})
auth = flow.authorize(storage)
puts "Credentials saved to #{CREDENTIALS_PATH}" unless auth.nil?
end
auth
end
# Initialize the API
client = Google::APIClient.new(:application_name => APPLICATION_NAME)
calendar_api = client.discovered_api('calendar', 'v3')
client.authorization = authorize
=begin
# Fetch the next 10 events for the user
results = client.execute!(
:api_method => calendar_api.events.list,
:parameters => {
:calendarId => 'primary',
:maxResults => 10,
:singleEvents => true,
:orderBy => 'startTime',
:timeMin => Time.now.iso8601 })
puts "Upcoming events:"
puts "No upcoming events found" if results.data.items.empty?
results.data.items.each do |event|
start = event.start.date || event.start.date_time
puts "- #{event.summary} (#{start})"
puts "- #{event.updated} (#{start})"
# puts "- #{event.accessRole} (#{start})"
##여기에 뭔가 생기는군
end
=end
event = {
'summary' => 'Google I/O 2015',
'location' => '800 Howard St., San Francisco, CA 94103',
'description' => 'A chance to hear more about Google\'s developer products.',
'start' => {
'dateTime' => '2015-05-28T09:00:00-07:00',
'timeZone' => 'America/Los_Angeles',
},
'end' => {
'dateTime' => '2015-05-28T17:00:00-07:00',
'timeZone' => 'America/Los_Angeles',
},
'recurrence' => [
'RRULE:FREQ=DAILY;COUNT=2'
],
'attendees' => [
{'email' => 'lpage#example.com'},
{'email' => 'sbrin#example.com'},
],
'reminders' => {
'useDefault' => false,
'overrides' => [
{'method' => 'email', 'minutes' => 24 * 60},
{'method' => 'sms', 'minutes' => 10},
],
},
}
results = client.execute!(
:api_method => calendar_api.events.insert,
:parameters => {
:calendarId => 'primary'},
:body_object => event)
event = results.data
puts "Event created: #{event.htmlLink}"
I copied the functioning part from the console site here. How can I allow the permission to use Calendar application?
For the basic read-only app, I was able to run the application because I have Calendar application enabled in the console setting but don't know how to proceed the next step. Please let me know how to solve this issue :)
I was in trouble same to you. You should change two points below:
Your application name is aimed to draw quick sample data by API. It is suitable to set your own application name. The name is one you registered in Google developer console.
You should change credentials path to your own. The path you wrote is only for quick start sample.
{File.join(Dir.home, '.credentials',"calendar-api-quickstart.json"")} >>>
{File.join(Dir.home, '.credentials',"client_secret.json")}

New calendar event, created using Google service account isn't sending invitaion email to the attendees

I am creating a new event in Google Calendar by using Google's service account, and I have also set sendNotifications to true, but after creating an event, invitation emails are not sending to the attendees ??
# new event to be created
event = {
'summary'=> summary,
'description'=> description,
'start'=> {'dateTime' => datetime },
'end' => {'dateTime' => datetime },
'sendNotifications' => true,
'sequence' => sequence,
'reminders' => {
'useDefault' => false,
'overrides' => [
{'minutes' => 60, 'method' => 'email'}
]
},
'attendees'=> [
{
'email'=> email
}
]
}
# build client
client = Google::APIClient.new application_name: "Test", application_version: "0.0.1"
key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, key_secret)
client.authorization = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:audience => 'https://accounts.google.com/o/oauth2/token',
:scope => 'https://www.googleapis.com/auth/calendar',
:issuer => ENV['SERVICE_ACCOUNT_EMAIL'],
:grant_type => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
:access_type => 'offline',
:signing_key => key
)
# fetch access token
client.authorization.fetch_access_token!
# create new event
service = client.discovered_api('calendar', 'v3')
client.execute(:api_method => service.acl.insert,
:parameters => {'calendarId' => 'primary'},
:body => JSON.dump(event),
:headers => {'Content-Type' => 'application/json'})
sendNotifications is a property of the request, not of an event. See the documentation of an insert here: https://developers.google.com/google-apps/calendar/v3/reference/events/insert You can also try the explorer to see how exactly requests should look like: https://developers.google.com/apis-explorer/#p/calendar/v3/ (don't forget to authenticate in the top right corner).

Invalid authorization name/value {x-li-auth-token}/{NAME_SEARCH:tdLy}

Im working on LinkedIn invitation API but I can't send the invitation to user, using people id from search result
Seached people result
**
"{\"people\":{\"total\":2,\"all\":[{\"api_standard_profile_request\":{\"headers\":{\"total\":1,\"all\":[{\"name\":\"x-li-auth-token\",\"value\":\"NAME_SEARCH:tdLy\"}]},\"url\":\"http://api.linkedin.com/v1/people/tp2Z82Xa_I\"},\"first_name\":\"Dev\",\"id\":\"tp2Z8sad2Xa_I\",\"last_name\":\"ruby\"},{\"api_standard_profile_request\":{\"headers\":{\"total\":1,\"all\":[{\"name\":\"x-li-auth-token\",\"value\":\"NAME_SEARCH:ZbY6\"}]},\"url\":\"http://api.linkedin.com/v1/people/TyaEtFbxzL\"},\"first_name\":\"dev\",\"id\":\"TyaEtFbsdsaxzL\",\"last_name\":\"ruby\"}]}}"**
And the invite methods following this
def send_invitation(options)
path = "/people/~/mailbox"
message = {
"recipients" => {
"values" => [
{
"person" => {
"_path" => "/people/id=#{options[:email]}",
"first-name" => options[:first_name],
"last-name" => options[:last_name]
}
}]
},
"subject" => "Invitation to connect.",
"body" => options[:body],
"item-content" => {
"invitation-request" => {
"connect-type" => "friend",
"authorization" => {"name" => "x-li-auth-token","value" => "NAME_SEARCH:tdLy"}
}
}
}
post(path, MultiJson.dump(message), "Content-Type" => "application/json")
end
So I am getting this error when I call client.send_invitation(options):
LinkedIn::Errors::GeneralError: (400): Invalid authorization name/value {x-li-auth-token}/{NAME_SEARCH:tdLy}
Working Fine
The name should be NAME_SEARCH and the value should be tdLy instead of what i have asked above. i have to split the value out of the oauth headers.
"authorization" => {:"name" => 'NAME_SEARCH',:"value" => 'tdLy'}

Google Calendar Service Account API leads to invalid grant

I have took the sample code from
http://code.google.com/p/google-api-ruby-client/source/browse/service_account/analytics.rb?repo=samples
however, I have been trying to get it working but it just keeps on giving, no matter how hard I try ! Here is the error I keep on getting
C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/signet-0.4.5/lib/signet/oauth_2/client.rb:875:in `fetch_access_token': Authorization failed. Server message: (Signet::Authorization
Error)
{
"error" : "invalid_grant"
}
from C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/signet-0.4.5/lib/signet/oauth_2/client.rb:888:in `fetch_access_token!'
How Do I solve this ?
Here is my complete code
require 'google/api_client'
require 'date'
require 'openssl'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
# Update these to match your own apps credentials
service_account_email = 'xxxxxx' # Email of service account
key_file = 'privatekey.p12' # File containing your private key
key_secret = 'notasecret' # Password to unlock private key
profileID = 'xxxxx' # Analytics profile ID.
client = Google::APIClient.new()
# Load our credentials for the service account
key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, key_secret)
client.authorization = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:audience => 'https://accounts.google.com/o/oauth2/token',
:scope => 'https://www.googleapis.com/auth/analytics.readonly',
:issuer => service_account_email,
:signing_key => key)
# Request a token for our service account
client.authorization.fetch_access_token!
analytics = client.discovered_api('analytics','v3')
startDate = DateTime.now.prev_month.strftime("%Y-%m-%d")
endDate = DateTime.now.strftime("%Y-%m-%d")
visitCount = client.execute(:api_method => analytics.data.ga.get, :parameters => {
'ids' => "ga:" + profileID,
'start-date' => startDate,
'end-date' => endDate,
'dimensions' => "ga:day,ga:month",
'metrics' => "ga:visits",
'sort' => "ga:month,ga:day"
})
print visitCount.data.column_headers.map { |c|
c.name
}.join("\t")
visitCount.data.rows.each do |r|
print r.join("\t"), "\n"
end
I have spent whole day to get this working. Please help. Thanks for your time.
Solved it !
My Computer clock was for some reason 4 hours late ! Corrected System Time, it lead to no error.
1 - Make Your you solve the SSL Error if you have any by using the Google API Faq.
It took me whole day, so I'm going to leave my solutions so in future no one has to go crazy like I did.
account_email = '#developer.gserviceaccount.com'
key_file = 'privatekey.p12'
key_secret = 'notasecret'
client = Google::APIClient.new()
key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, key_secret)
client.authorization = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:audience => 'https://accounts.google.com/o/oauth2/token',
:scope => 'https://www.googleapis.com/auth/calendar',
:issuer => account_email,
:signing_key => key)
# # Request a token for our service account
client.authorization.fetch_access_token!
service = client.discovered_api('calendar', 'v3')
Example to execute something shall be like in similar fashion.
#event = {
'summary' => '',
'location' => 'this is where the location goes',
'description' => 'desc',
'start' => {
'dateTime' => '2013-02-08T10:00:00.000-07:00' # Date with :- offset so (yyyy-mm-dd T hh:mm:ss.000-offset)
},
'end' => {
'dateTime' => '2013-02-08T10:25:00.000-07:00' # Date with :- offset so (yyyy-mm-dd T hh:mm:ss.000-offset)
}
}
# Create event using the json structure
result = client.execute(:api_method => service.events.insert,
:parameters => {'calendarId' => '**'},
:body => JSON.dump(#event),
:headers => {'Content-Type' => 'application/json'})

Resources