google_oauth_calendar 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +72 -0
- data/Rakefile +2 -0
- data/google_oauth_calendar.gemspec +17 -0
- data/lib/google_oauth_calendar.rb +4 -0
- data/lib/google_oauth_calendar/version.rb +3 -0
- data/lib/rails/generators/google_oauth_calendar/install/install_generator.rb +83 -0
- data/lib/rails/generators/google_oauth_calendar/install/templates/client_builder.rb +29 -0
- data/lib/rails/generators/google_oauth_calendar/install/templates/home_controller.rb +14 -0
- data/lib/rails/generators/google_oauth_calendar/install/templates/index.html.erb +15 -0
- data/lib/rails/generators/google_oauth_calendar/install/templates/omniauth.rb +11 -0
- data/lib/rails/generators/google_oauth_calendar/install/templates/sessions_controller.rb +31 -0
- data/lib/rails/generators/google_oauth_calendar/install/templates/user.rb +17 -0
- metadata +61 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Ben Johnson
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# GoogleOauthCalendar
|
2
|
+
|
3
|
+
This provides a generator that installs everything you need to be able to authenticate users against
|
4
|
+
their Google identity (via oauth2), and then use the google apis to start interacting with their calendars.
|
5
|
+
This isn't limited to Google Calendars, but it's a nice starter example to demonstrate their services.
|
6
|
+
|
7
|
+
Rather than
|
8
|
+
the individual instructions at each in each gem, and stubbing your toe a half dozen times in the process, this is
|
9
|
+
a one-stop generator.
|
10
|
+
|
11
|
+
Specifically, it
|
12
|
+
|
13
|
+
* creates a User model with name & email pulled from Google, and a place to store their access and refresh token
|
14
|
+
* initializes omniauth to use the google-oauth2 strategy for signin
|
15
|
+
* creates a SessionsController to react to signin/signout
|
16
|
+
* installs a basic root controller that has view showing signin/signout links,
|
17
|
+
and queries the list of the user's calendars via the google/api_client
|
18
|
+
|
19
|
+
This gem allows you to install these features after your app already exists, rather than using an application
|
20
|
+
template such as [rails_apps_composer](https://github.com/RailsApps/rails_apps_composer). This way, it makes
|
21
|
+
fewer assumptions about your other app preferences.
|
22
|
+
|
23
|
+
## Configuring Google API
|
24
|
+
|
25
|
+
You need to configure an API instance at Google for your app's use. This becomes the trust link
|
26
|
+
between the systems. You can use a regular google identity for this, Google Apps for Business or other
|
27
|
+
paid services are not required, assuming you can deal with their usage limits.
|
28
|
+
|
29
|
+
1. Go to to the [Google API Console](https://code.google.com/apis/console/), and create a new project.
|
30
|
+
(The name doesn't matter, but will probably match your rails project name)
|
31
|
+
1. Go to the service tab, and enable **Calendar API**
|
32
|
+
1. Go to the **API Access** tab, and create an OAuth 2.0 client ID
|
33
|
+
1. pick a project name
|
34
|
+
1. choose "web application" as the application type
|
35
|
+
1. for "your site or hostname" choose "more options" and use
|
36
|
+
|
37
|
+
http://localhost:3000/auth/google_oauth2/callback
|
38
|
+
1. copy the client ID and secret into environment variables, for example
|
39
|
+
|
40
|
+
export GOOGLE_CLIENT_ID = "YOUR_CLIENT_ID"
|
41
|
+
export GOOGLE_CLIENT_SECRET = "YOUR_CLIENT_SECRET"
|
42
|
+
## Installation
|
43
|
+
|
44
|
+
Add this line to your application's Gemfile:
|
45
|
+
|
46
|
+
gem 'google_oauth_calendar' , :git => 'git@github.com:deafgreatdane/google_oauth_calendar.git'
|
47
|
+
|
48
|
+
And then execute:
|
49
|
+
|
50
|
+
$ bundle
|
51
|
+
$ rails generate google_oauth_calendar:install
|
52
|
+
$ rake db:migrate
|
53
|
+
$ rails server
|
54
|
+
|
55
|
+
When you click the "signin" link, you'll be redirected to google, asked to confirm your app's use of calendar
|
56
|
+
APIs, then it direct back to your home page, signed in, and list your calendars.
|
57
|
+
|
58
|
+
At this point, you can remove the gem from your gemfile, since it's only the generator
|
59
|
+
|
60
|
+
## Where to go from here
|
61
|
+
|
62
|
+
Now you can get to work at adding the real features using your preferred patterns. Some things you'll
|
63
|
+
probably end up doing:
|
64
|
+
|
65
|
+
* add a UserController for seeing who has connected
|
66
|
+
* add "filter authenticate_user!" to your secure controllers
|
67
|
+
* learn more about the [calendar or other google apis](http://code.google.com/p/google-api-ruby-client/wiki/SupportedAPIs)
|
68
|
+
via the [google-api-client](http://code.google.com/p/google-api-ruby-client/)
|
69
|
+
* add more "redirect URLs" to your Google API console, corresponding to your stage & production urls.
|
70
|
+
* add error handling for chatting with Google
|
71
|
+
|
72
|
+
Feedback and contributions are welcome, just file an issue or create pull request
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/google_oauth_calendar/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Ben Johnson"]
|
6
|
+
gem.email = ["deafgreatdane@gmail.com"]
|
7
|
+
gem.description = %q{a generator for adding google-based users via omniauth, and querying google calendars}
|
8
|
+
gem.summary = %q{just run rails generate google_oauth_calendar:install }
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "google_oauth_calendar"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = GoogleOauthCalendar::VERSION
|
17
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module GoogleOauthCalendar
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
desc "This generator installs all the snippets for users via google oauth"
|
5
|
+
def self.source_root
|
6
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_files
|
10
|
+
# the gems we're using
|
11
|
+
gem "omniauth", ">= 1.0.3"
|
12
|
+
gem "omniauth-google-oauth2"
|
13
|
+
gem 'google-api-client'
|
14
|
+
|
15
|
+
# wire up the omniauth strategy. This assumes you have environment
|
16
|
+
# variables GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET
|
17
|
+
# such as
|
18
|
+
# export GOOGLE_CLIENT_ID = "YOUR_CLIENT_ID"
|
19
|
+
# export GOOGLE_CLIENT_SECRET = "YOUR_CLIENT_SECRET"
|
20
|
+
template 'omniauth.rb', 'config/initializers/omniauth.rb'
|
21
|
+
|
22
|
+
# this is the controller that connects oauth to user user model
|
23
|
+
template 'sessions_controller.rb', 'app/controllers/sessions_controller.rb'
|
24
|
+
route("match '/auth/:provider/callback' => 'sessions#create'")
|
25
|
+
route("match '/signin' => 'sessions#new', :as => :signin")
|
26
|
+
route("match '/signout' => 'sessions#destroy', :as => :signout")
|
27
|
+
route("match '/auth/failure' => 'sessions#failure'")
|
28
|
+
|
29
|
+
# setup the user info
|
30
|
+
generate("model User provider:string uid:string name:string email:string token:string refresh_token:string token_expires_at:datetime")
|
31
|
+
|
32
|
+
inject_into_class "app/models/user.rb", User, <<-USER_METHODS
|
33
|
+
def self.create_with_omniauth(auth)
|
34
|
+
create! do |user|
|
35
|
+
user.provider = auth['provider']
|
36
|
+
user.uid = auth['uid']
|
37
|
+
if auth['info']
|
38
|
+
user.name = auth['info']['name'] || ""
|
39
|
+
user.email = auth['info']['email'] || ""
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
USER_METHODS
|
44
|
+
|
45
|
+
|
46
|
+
inject_into_class "app/controllers/application_controller.rb", ApplicationController ,<<APP_HELPERS
|
47
|
+
helper_method :current_user
|
48
|
+
helper_method :user_signed_in?
|
49
|
+
helper_method :correct_user?
|
50
|
+
|
51
|
+
private
|
52
|
+
def current_user
|
53
|
+
@current_user ||= User.find(session[:user_id]) if session[:user_id]
|
54
|
+
end
|
55
|
+
|
56
|
+
def user_signed_in?
|
57
|
+
return true if current_user
|
58
|
+
end
|
59
|
+
|
60
|
+
def correct_user?
|
61
|
+
@user = User.find(params[:id])
|
62
|
+
unless current_user == @user
|
63
|
+
redirect_to root_url, :alert => "Access denied."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def authenticate_user!
|
68
|
+
if !current_user
|
69
|
+
redirect_to root_url, :alert => 'You need to sign in for access to this page.'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
APP_HELPERS
|
73
|
+
|
74
|
+
# setup the home controller
|
75
|
+
template 'home_controller.rb', 'app/controllers/home_controller.rb'
|
76
|
+
copy_file 'index.html.erb', 'app/views/home/index.html.erb'
|
77
|
+
copy_file 'client_builder.rb', 'lib/client_builder.rb'
|
78
|
+
remove_file 'public/index.html'
|
79
|
+
route("root :to => 'home#index'")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'google/api_client'
|
2
|
+
|
3
|
+
class ClientBuilder
|
4
|
+
|
5
|
+
def self.get_client(user)
|
6
|
+
client = Google::APIClient.new
|
7
|
+
client.authorization.scope = 'https://www.googleapis.com/auth/calendar'
|
8
|
+
client.authorization.access_token = get_current_token(user)
|
9
|
+
client
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.get_current_token(user)
|
13
|
+
if (user.token.nil? || (user.token_expires_at.nil? || user.token_expires_at <Time.now))
|
14
|
+
# fetch new value here.
|
15
|
+
client = OAuth2::Client.new(
|
16
|
+
ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'],
|
17
|
+
:site => "https://accounts.google.com",
|
18
|
+
:token_url => "/o/oauth2/token",
|
19
|
+
:authorize_url => "/o/oauth2/auth")
|
20
|
+
access_token = OAuth2::AccessToken.from_hash(client,
|
21
|
+
{:refresh_token => user.refresh_token})
|
22
|
+
access_token = access_token.refresh!
|
23
|
+
user.token = access_token.token
|
24
|
+
user.token_expires_at = Time.now + access_token.expires_in
|
25
|
+
user.save
|
26
|
+
end
|
27
|
+
user.token
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class HomeController < ApplicationController
|
2
|
+
require 'google/api_client'
|
3
|
+
require 'client_builder'
|
4
|
+
def index
|
5
|
+
if (user_signed_in? )
|
6
|
+
client = ClientBuilder.get_client(current_user)
|
7
|
+
service = client.discovered_api('calendar', 'v3')
|
8
|
+
result = client.execute(:api_method => service.calendar_list.list)
|
9
|
+
|
10
|
+
@calendars = result.data
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<h1>Home</h1>
|
2
|
+
|
3
|
+
<p>
|
4
|
+
<%- if user_signed_in? %>
|
5
|
+
Greetings <%= current_user.name %>
|
6
|
+
[<%= link_to "sign out", signout_path %>]
|
7
|
+
<ul>
|
8
|
+
<% @calendars.items.each do |calendar| %>
|
9
|
+
<li><%= calendar["summary"] %></li>
|
10
|
+
<% end %>
|
11
|
+
</ul>
|
12
|
+
<% else %>
|
13
|
+
[<%= link_to "sign in", signin_path %>]
|
14
|
+
<% end %>
|
15
|
+
</p>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
2
|
+
scopes = [
|
3
|
+
# we need the profile scope in order to login
|
4
|
+
"https://www.googleapis.com/auth/userinfo.profile",
|
5
|
+
# this and other scopes could be added, but match them up with the
|
6
|
+
# features you requested in your API Console
|
7
|
+
"https://www.googleapis.com/auth/calendar"
|
8
|
+
]
|
9
|
+
provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'],
|
10
|
+
{:scope =>scopes.join(" ")}
|
11
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class SessionsController < ApplicationController
|
2
|
+
|
3
|
+
def new
|
4
|
+
redirect_to '/auth/google_oauth2'
|
5
|
+
end
|
6
|
+
|
7
|
+
def create
|
8
|
+
auth = request.env["omniauth.auth"]
|
9
|
+
user = User.where(:provider => auth['provider'],
|
10
|
+
:uid => auth['uid']).first || User.create_with_omniauth(auth)
|
11
|
+
user.token = auth[:credentials][:token];
|
12
|
+
user.token_expires_at = Time.at(auth[:credentials][:expires_at])
|
13
|
+
user.refresh_token = auth[:credentials][:refresh_token]
|
14
|
+
user.save
|
15
|
+
|
16
|
+
session[:user_id] = user.id
|
17
|
+
redirect_to root_url, :notice => 'Signed in!'
|
18
|
+
end
|
19
|
+
|
20
|
+
def destroy
|
21
|
+
reset_session
|
22
|
+
redirect_to root_url, :notice => 'Signed out!'
|
23
|
+
end
|
24
|
+
|
25
|
+
def failure
|
26
|
+
# if you want to debug something better, this is the object you want
|
27
|
+
#auth = request.env["omniauth.error"]
|
28
|
+
redirect_to root_url, :alert => "Authentication error: #{params[:message].humanize}"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
attr_accessible :email, :name, :provider, :uid
|
3
|
+
attr_accessible :provider, :uid, :name, :email
|
4
|
+
|
5
|
+
def self.create_with_omniauth(auth)
|
6
|
+
create! do |user|
|
7
|
+
user.provider = auth['provider']
|
8
|
+
user.uid = auth['uid']
|
9
|
+
if auth['info']
|
10
|
+
user.name = auth['info']['name'] || ""
|
11
|
+
user.email = auth['info']['email'] || ""
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: google_oauth_calendar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ben Johnson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-26 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: a generator for adding google-based users via omniauth, and querying
|
15
|
+
google calendars
|
16
|
+
email:
|
17
|
+
- deafgreatdane@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- google_oauth_calendar.gemspec
|
28
|
+
- lib/google_oauth_calendar.rb
|
29
|
+
- lib/google_oauth_calendar/version.rb
|
30
|
+
- lib/rails/generators/google_oauth_calendar/install/install_generator.rb
|
31
|
+
- lib/rails/generators/google_oauth_calendar/install/templates/client_builder.rb
|
32
|
+
- lib/rails/generators/google_oauth_calendar/install/templates/home_controller.rb
|
33
|
+
- lib/rails/generators/google_oauth_calendar/install/templates/index.html.erb
|
34
|
+
- lib/rails/generators/google_oauth_calendar/install/templates/omniauth.rb
|
35
|
+
- lib/rails/generators/google_oauth_calendar/install/templates/sessions_controller.rb
|
36
|
+
- lib/rails/generators/google_oauth_calendar/install/templates/user.rb
|
37
|
+
homepage: ''
|
38
|
+
licenses: []
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.8.24
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: just run rails generate google_oauth_calendar:install
|
61
|
+
test_files: []
|