Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
MSch committed Sep 12, 2010
0 parents commit dbb28c1
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,5 @@
pkg/*
*.gem
.bundle
.rvmrc
session.vim
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,4 @@
source :gemcutter

# Specify your gem's dependencies in devise-twitter.gemspec
gemspec
30 changes: 30 additions & 0 deletions Gemfile.lock
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,30 @@
PATH
remote: .
specs:
devise-twitter (0.0.1)
devise (>= 1.1.0)
warden_oauth (~> 0.1.1)

GEM
remote: http://rubygems.org/
specs:
bcrypt-ruby (2.1.2)
devise (1.1.2)
bcrypt-ruby (~> 2.1.2)
warden (~> 0.10.7)
oauth (0.4.3)
rack (1.2.1)
warden (0.10.7)
rack (>= 1.0.0)
warden_oauth (0.1.1)
oauth
warden (>= 0.8.1)

PLATFORMS
ruby

DEPENDENCIES
bundler (>= 1.0.0)
devise (>= 1.1.0)
devise-twitter!
warden_oauth (~> 0.1.1)
2 changes: 2 additions & 0 deletions Rakefile
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,2 @@
require 'bundler'
Bundler::GemHelper.install_tasks
25 changes: 25 additions & 0 deletions devise-twitter.gemspec
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
require File.expand_path("../lib/devise/twitter/version", __FILE__)

Gem::Specification.new do |s|
s.name = "devise-twitter"
s.version = Devise::Twitter::VERSION
s.platform = Gem::Platform::RUBY
s.authors = ['Martin Schuerrer']
s.email = ['martin@schuerrer.org']
s.homepage = "http://rubygems.org/gems/devise-twitter"
s.summary = "Out of the box support for signing in via Twitter and connecting an existing account to Twitter"
s.description = ""

s.required_rubygems_version = ">= 1.3.6"
s.rubyforge_project = "devise-twitter"

# FIXME: Seems like bundler can't handle [">= 1.1.0", "< 1.3.0"]
s.add_dependency "devise", ">= 1.1.0"
s.add_dependency "warden_oauth", "~> 0.1.1"
s.add_development_dependency "bundler", ">= 1.0.0"

s.files = `git ls-files`.split("\n")
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
s.require_path = 'lib'
end
13 changes: 13 additions & 0 deletions lib/devise-twitter.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,13 @@
module Devise
module Twitter
end
end

require "rack"
require "warden"
require "oauth"
require "warden_oauth"
require "devise"
require "devise/twitter/rack"
require "devise/twitter/warden"
require "devise/twitter/version"
64 changes: 64 additions & 0 deletions lib/devise/twitter/rack.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,64 @@
module Devise
module Twitter
module Rack
Signin = proc do |env|
warden = env['warden']
session = env['rack.session']
request = ::Rack::Request.new(env)
scope = env["devise.mapping"].singular

if request.params.include?('oauth_token')
# We got a redirect from Twitter back

# Perform _only_ the twitter_oauth strategy.
# Emulate _perform_authentication in _warden/proxy.rb
strategy = warden.send(:_fetch_strategy, :twitter_oauth, scope)
strategy.authenticate!
if strategy.user
warden.set_user(strategy.user, :event => :authentication, :scope => scope)
end

redirect_to Warden::OAuth::Utils.host_with_port(request)
else
# Perform the redirect to Twitter
strategy = warden.send(:_fetch_strategy, :twitter_oauth, scope)

# warden_oauth would always redirect to / so we need to hook into it
request_token = strategy.consumer.get_request_token(:oauth_callback => request.url)
strategy.instance_variable_set(:@request_token, request_token)

# warden_oauth does exactly this if params.include? warden_oauth_provider
# which we also hack around
strategy.send(:store_request_token_on_session)
redirect_to request_token.authorize_url
end
end

Connect = proc do |env|
# Check that user exists in DB, otherwise we'll get 'user with access token not found'
# But since connecting to twitter only makes sense for existing users that's ok
# TODO: If our user is unobtrusive redirect_to :back
scope = env["devise.mapping"].singular
env["warden.#{scope}.twitter.perform_connect"] = true

Signin.call(env)
end

private

# Stolen from action_dispatch/routing/mapper.rb
def self.redirect_to(url)
status = 302 # Found
body = %(<html><body>You are being <a href="#{ERB::Util.h(url.to_s)}">redirected</a>.</body></html>)

headers = {
'Location' => url.to_s,
'Content-Type' => 'text/html',
'Content-Length' => body.length.to_s
}

[ status, headers, [body] ]
end
end
end
end
5 changes: 5 additions & 0 deletions lib/devise/twitter/version.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,5 @@
module Devise
module Twitter
VERSION = "0.0.1"
end
end
41 changes: 41 additions & 0 deletions lib/devise/twitter/warden.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,41 @@
Warden::OAuth.access_token_user_finder(:twitter) do |access_token|
perform_connect = (env["warden.#{@scope}.twitter.perform_connect"] == true)
twitter_handle = access_token.params[:screen_name]

if perform_connect
# Add twitter_handle to current user
already_existing_user = User.find_by_twitter_handle(twitter_handle)
if already_existing_user.blank?
# We don't know anyone with this handle, therefore continue with connecting
user = @env['warden'].user
user.twitter_handle = twitter_handle
user.twitter_oauth_token = access_token.token
user.twitter_oauth_secret = access_token.secret
user.save
return user
else
# We already have such a user in our DB
session["warden.#{@scope}.twitter.connected_user.key"] = already_existing_user.id
return @env['warden'].user
end
else
previous_user = @env['warden'].user

# Try to find user by token
user = User.find_by_twitter_oauth_token_and_twitter_oauth_secret(access_token.token, access_token.secret)

# Since we are logging in a new user we want to make sure the before_logout hook is called
@env['warden'].logout if previous_user.present?

if user.nil?
# Create user if we don't know him yet
user = User.new
user.twitter_handle = twitter_handle
user.twitter_oauth_token = access_token.token
user.twitter_oauth_secret = access_token.secret
user.save
end

return user
end
end

0 comments on commit dbb28c1

Please sign in to comment.