Skip to content

Instantly share code, notes, and snippets.

@masuidrive
Last active August 29, 2015 14:03
Show Gist options
  • Save masuidrive/20049711692b5f5885c8 to your computer and use it in GitHub Desktop.
Save masuidrive/20049711692b5f5885c8 to your computer and use it in GitHub Desktop.
Google認証用のRails project template

Install

mkdir foo
cd foo

curl -o "Vagrantfile" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/171c5027732476f433b6cb97963382e3896fada0/Vagrantfile"
vagrant up && vagrant ssh
# 以下、vagrant内
cd /vagrant
gem install rails --no-rdoc --no-ri

rails new ./ --database=postgresql

echo 'gem "google-api-client", "~> 0.7.1"' >> Gemfile
echo 'group :production do' >> Gemfile
echo '  gem "newrelic_rpm"' >> Gemfile
echo '  gem "rails_12factor"' >> Gemfile
echo 'end' >> Gemfile
bundle install

psql template1 -c "CREATE DATABASE development"
psql template1 -c "CREATE DATABASE test"

curl -o "config/database.yml" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/50f40d245409129c64ef553d7fa228e7092d495f/database.yml"

rails g model team
rails g model google_account
rails g model user

rm db/migrate/*.rb
curl -o "db/migrate/20140101000000_create_google_auth.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/e344ef51ec54e1312637d0a81455bb69443ecbf7/20140101000000_create_google_auth.rb"
rake db:migrate

rm app/models/*.rb
curl -o "app/models/team.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/ac306295857f09be9d6428f4cd68a0144df127f5/team.rb"
curl -o "app/models/user.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/22401ffd6941843999ed8101313239c7d502ec25/user.rb"
curl -o "app/models/google_account.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/118bb5675db0eeeeb86fdfab7c6a5c23233f1522/google_account.rb"

rails g controller oauth/google
rails g controller sessions
rails g controller dashboard show
curl -o "app/controllers/sessions_controller.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/71a95d59f02578f58bbbc096ffc943e7505d6db3/sessions_controller.rb"
curl -o "app/controllers/oauth/google_controller.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/5b441e3ddb090b1a339f3cd2689f13b0fbf17d6f/google_controller.rb"
curl -o "app/controllers/dashboard_controller.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/d563863b34dfbe6814775fa6ce7e48880b32fe87/dashboard_controller.rb"
curl -o "app/views/dashboard/show.html.erb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/c49ad450a6630b5dd6bb7178491930c594dbeedc/dashboard_show.html.erb"
curl -o "app/helpers/application_helper.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/d32000a590e478fc405bc2141b1211dc72f017dd/application_helper.rb"

curl -o "app/controllers/concerns/require_team.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/de5c479b535c9c9308124c04628f88773f133410/require_team.rb"
curl -o "app/controllers/concerns/authentication.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/c99e45edb7f2308800506a5799b3c836cf09e629/authentication.rb"

curl -o "config/routes.rb" "https://gist.githubusercontent.com/masuidrive/20049711692b5f5885c8/raw/7fe7c02dac22e3a9c31b9d1114a3d2d61c5cd6c8/routes.rb"

config/google.yml

Google認証のKeyを設定。

https://console.developers.google.com/project から生成

development:
  client_id: 0000000000-apps.googleusercontent.com
  client_secret: AAAA-BBBB-CCCC

production:
  client_id: 9999999999-.apps.googleusercontent.com
  client_secret: DDDD-EEEE-FFFFF
class CreateGoogleAuth < ActiveRecord::Migration
def change
create_table :teams do |t|
t.string :name
t.string :domain, unique: true
t.boolean :active, default: true
t.timestamps
end
create_table :users do |t|
t.integer :google_account_id, index: true
t.integer :team_id, index: true
t.string :key, unique: true
t.string :name
t.string :email
t.string :locale
t.text :icon_url
t.timestamps
end
create_table :google_accounts do |t|
t.string :google_id, unique: true
t.string :email, unique: true
t.string :name
t.string :hd, index: true
t.string :refresh_token
t.string :access_token
t.integer :expires_in
t.integer :issued_at
t.timestamps
end
end
end
module ApplicationHelper
def current_user
@current_user ||= controller.send(:current_user)
end
end
module Concerns::Authentication
extend ActiveSupport::Concern
included do
# before_filter :require_login
end
module ClassMethods
end
private
def current_account
@current_account ||= GoogleAccount.find(session[:ga_id]) unless session[:ga_id].blank?
rescue
@current_account = nil
end
private
def current_user
@current_user ||= User.find(session[:user_id]) unless session[:user_id].blank?
rescue
@current_user = nil
end
private
def current_team
@current_team ||= Team.find(session[:team_id]) unless session[:team_id].blank?
rescue
@current_team = nil
end
private
def require_login
if current_account
true
else
redirect_to '/'
end
end
end
class DashboardController < ApplicationController
include Concerns::Authentication
include Concerns::RequireTeam
before_filter :require_login
before_filter :require_team
def show
end
end
<h1>Dashboard#show</h1>
I'm <%= current_user.name %>.
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
#
default: &default
adapter: postgresql
encoding: unicode
pool: 5
username: vagrant
password:
development:
<<: *default
database: development
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: test
production:
<<: *default
database: production
class GoogleAccount < ActiveRecord::Base
has_many :users
has_many :teams, through: :users
end
require 'google/api_client'
class Oauth::GoogleController < ApplicationController
before_filter :prepare_variables
def new
reset_session
redirect_to @client.authorization.authorization_uri.to_s
end
def callback
reset_session
@client.authorization.code = params[:code]
@client.authorization.fetch_access_token!
result = @client.execute(uri: 'https://www.googleapis.com/plus/v1/people/me')
unless result.data['domain'].blank?
account = GoogleAccount.find_or_create_by(google_id: result.data['id'])
account.update_attributes! email: result.data['emails'][0]['value'],
name: result.data['displayName'], hd: result.data['domain'],
access_token: @client.authorization.access_token,
refresh_token: @client.authorization.refresh_token,
expires_in: @client.authorization.expires_in,
issued_at: @client.authorization.issued_at
# google apps domainに合ったチームがなければ作成
team = Team.find_by(domain: result.data['domain'])
unless team
team = Team.create!(domain: result.data['domain'], name: result.data['domain'])
ActionType::create_defaults(team)
Stage::create_defaults(team)
end
icon_url = result.data['image']['url'].gsub(/\?sz=\d+$/,'')
if account.users.empty?
user = account.users.create!(name: account.name, email: account.email, locale: result.data['language'], icon_url: icon_url, team_id: team.id)
else
# todo: URLなどをみて適当なユーザを選択する
user = account.users.first
user.update_attributes!(name: account.name, email: account.email, locale: result.data['language'], icon_url: icon_url)
end
session[:ga_id] = account.id
session[:user_id] = user.id
session[:team_id] = team.id
redirect_to dashboard_path(team_id: team.domain)
else
render text: "Require Google Apps account"
end
rescue
redirect_to :sessions_new
end
private
def prepare_variables
@@config ||= YAML.load_file(File.join(Rails.root, 'config/google.yml'))[Rails.env]
@client = Google::APIClient.new
@client.authorization.client_id = @@config['client_id']
@client.authorization.client_secret = @@config['client_secret']
@client.authorization.scope = "profile email"
@client.authorization.redirect_uri = oauth_google_callback_url
end
end
module Concerns::RequireTeam
extend ActiveSupport::Concern
included do
# before_filter :require_team
end
module ClassMethods
end
private
def require_team
if params[:team_id].blank?
head :not_found
else
@team = Team.find_by(domain: params[:team_id].downcase)
if @team.nil?
redirect_to session_url
elsif [email protected]?
head :forbidden
end
end
end
end
Rails.application.routes.draw do
scope '/:team_id', constraints: { team_id: /[-\w]+\.[-.\w]+/ } do
get '/', controller: 'dashboard', action: 'show', as: 'dashboard'
end
# root 'welcome#index'
resource :sessions, only: %i(new destroy)
namespace :oauth do
namespace :google do
get 'new'
get 'callback'
end
end
end
class SessionsController < ApplicationController
def new
redirect_to :oauth_google_new
end
def destroy
reset_session
redirect_to '/'
end
end
class Team < ActiveRecord::Base
has_many :users, dependent: :destroy
end
class User < ActiveRecord::Base
belongs_to :team
belongs_to :google_account
end
Vagrant.configure("2") do |config|
config.vm.box = "heroku"
config.vm.box_url = "http://dl.dropbox.com/u/1906634/heroku.box"
config.vm.network :forwarded_port, guest: 3000, host: 5000
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment