121 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
		
		
			
		
	
	
			121 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| 
								 | 
							
								# Copyright 2015 Google Inc.
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# Licensed under the Apache License, Version 2.0 (the "License");
							 | 
						||
| 
								 | 
							
								# you may not use this file except in compliance with the License.
							 | 
						||
| 
								 | 
							
								# You may obtain a copy of the License at
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								#      http://www.apache.org/licenses/LICENSE-2.0
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# Unless required by applicable law or agreed to in writing, software
							 | 
						||
| 
								 | 
							
								# distributed under the License is distributed on an "AS IS" BASIS,
							 | 
						||
| 
								 | 
							
								# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
							 | 
						||
| 
								 | 
							
								# See the License for the specific language governing permissions and
							 | 
						||
| 
								 | 
							
								# limitations under the License.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								require 'sinatra'
							 | 
						||
| 
								 | 
							
								require 'googleauth'
							 | 
						||
| 
								 | 
							
								require 'googleauth/stores/redis_token_store'
							 | 
						||
| 
								 | 
							
								require 'google/apis/drive_v3'
							 | 
						||
| 
								 | 
							
								require 'google/apis/calendar_v3'
							 | 
						||
| 
								 | 
							
								require 'google-id-token'
							 | 
						||
| 
								 | 
							
								require 'dotenv'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								LOGIN_URL = '/'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								configure do
							 | 
						||
| 
								 | 
							
								  Dotenv.load
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Google::Apis::ClientOptions.default.application_name = 'Ruby client samples'
							 | 
						||
| 
								 | 
							
								  Google::Apis::ClientOptions.default.application_version = '0.9'
							 | 
						||
| 
								 | 
							
								  Google::Apis::RequestOptions.default.retries = 3
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  enable :sessions
							 | 
						||
| 
								 | 
							
								  set :show_exceptions, false
							 | 
						||
| 
								 | 
							
								  set :client_id, Google::Auth::ClientId.new(ENV['GOOGLE_CLIENT_ID'],
							 | 
						||
| 
								 | 
							
								                                             ENV['GOOGLE_CLIENT_SECRET'])
							 | 
						||
| 
								 | 
							
								  set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
							 | 
						||
| 
								 | 
							
								end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								helpers do
							 | 
						||
| 
								 | 
							
								  # Returns credentials authorized for the requested scopes. If no credentials are available,
							 | 
						||
| 
								 | 
							
								  # redirects the user to authorize access.
							 | 
						||
| 
								 | 
							
								  def credentials_for(scope)
							 | 
						||
| 
								 | 
							
								    authorizer = Google::Auth::WebUserAuthorizer.new(settings.client_id, scope, settings.token_store)
							 | 
						||
| 
								 | 
							
								    user_id = session[:user_id]
							 | 
						||
| 
								 | 
							
								    redirect LOGIN_URL if user_id.nil?
							 | 
						||
| 
								 | 
							
								    credentials = authorizer.get_credentials(user_id, request)
							 | 
						||
| 
								 | 
							
								    if credentials.nil?
							 | 
						||
| 
								 | 
							
								      redirect authorizer.get_authorization_url(login_hint: user_id, request: request)
							 | 
						||
| 
								 | 
							
								    end
							 | 
						||
| 
								 | 
							
								    credentials
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  def resize(url, width)
							 | 
						||
| 
								 | 
							
								    url.sub(/s220/, sprintf('s%d', width))
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Home page
							 | 
						||
| 
								 | 
							
								get('/') do
							 | 
						||
| 
								 | 
							
								  @client_id = settings.client_id.id
							 | 
						||
| 
								 | 
							
								  erb :home
							 | 
						||
| 
								 | 
							
								end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Log in the user by validating the identity token generated by the Google Sign-In button.
							 | 
						||
| 
								 | 
							
								# This checks that the token is signed by Google, current, and is intended for this application.
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								post('/signin') do
							 | 
						||
| 
								 | 
							
								  audience = settings.client_id.id
							 | 
						||
| 
								 | 
							
								  # Important: The google-id-token gem is not production ready. If using, consider fetching and
							 | 
						||
| 
								 | 
							
								  # supplying the valid keys separately rather than using the built-in certificate fetcher.
							 | 
						||
| 
								 | 
							
								  validator = GoogleIDToken::Validator.new
							 | 
						||
| 
								 | 
							
								  claim = validator.check(params['id_token'], audience, audience)
							 | 
						||
| 
								 | 
							
								  if claim
							 | 
						||
| 
								 | 
							
								    session[:user_id] = claim['sub']
							 | 
						||
| 
								 | 
							
								    session[:user_email] = claim['email']
							 | 
						||
| 
								 | 
							
								    200
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    logger.info('No valid identity token present')
							 | 
						||
| 
								 | 
							
								    401
							 | 
						||
| 
								 | 
							
								  end
							 | 
						||
| 
								 | 
							
								end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Retrieve the 10 most recently modified files in Google Drive
							 | 
						||
| 
								 | 
							
								get('/drive') do
							 | 
						||
| 
								 | 
							
								  drive = Google::Apis::DriveV3::DriveService.new
							 | 
						||
| 
								 | 
							
								  drive.authorization = credentials_for(Google::Apis::DriveV3::AUTH_DRIVE)
							 | 
						||
| 
								 | 
							
								  @result = drive.list_files(page_size: 10,
							 | 
						||
| 
								 | 
							
								                             fields: 'files(name,modified_time,web_view_link),next_page_token')
							 | 
						||
| 
								 | 
							
								  erb :drive
							 | 
						||
| 
								 | 
							
								end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Retrieve the next 10 upcoming events from Google Calendar
							 | 
						||
| 
								 | 
							
								get('/calendar') do
							 | 
						||
| 
								 | 
							
								  calendar = Google::Apis::CalendarV3::CalendarService.new
							 | 
						||
| 
								 | 
							
								  calendar.authorization = credentials_for(Google::Apis::CalendarV3::AUTH_CALENDAR)
							 | 
						||
| 
								 | 
							
								  calendar_id = 'primary'
							 | 
						||
| 
								 | 
							
								  @result = calendar.list_events(calendar_id,
							 | 
						||
| 
								 | 
							
								                                 max_results: 10,
							 | 
						||
| 
								 | 
							
								                                 single_events: true,
							 | 
						||
| 
								 | 
							
								                                 order_by: 'startTime',
							 | 
						||
| 
								 | 
							
								                                 time_min: Time.now.iso8601)
							 | 
						||
| 
								 | 
							
								  erb :calendar
							 | 
						||
| 
								 | 
							
								end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# Callback for authorization requests. This saves the autorization code and
							 | 
						||
| 
								 | 
							
								# redirects back to the URL that originally requested authorization. The code is
							 | 
						||
| 
								 | 
							
								# redeemed on the next request.
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# Important: While the deferred approach is generally easier, it doesn't play well
							 | 
						||
| 
								 | 
							
								# with developer mode and sinatra's default cookie-based session implementation. Changes to the
							 | 
						||
| 
								 | 
							
								# session state are lost if the page doesn't render due to error, which can lead to further
							 | 
						||
| 
								 | 
							
								# errors indicating the code has already been redeemed.
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# Disabling show_exceptions or using a different session provider (E.g. Rack::Session::Memcache)
							 | 
						||
| 
								 | 
							
								# avoids the issue.
							 | 
						||
| 
								 | 
							
								get('/oauth2callback') do
							 | 
						||
| 
								 | 
							
								  target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
							 | 
						||
| 
								 | 
							
								  redirect target_url
							 | 
						||
| 
								 | 
							
								end
							 |