Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fixed everything up

  • Loading branch information...
commit 1d437509e02b1704fa94e997f870dcf9973a1801 1 parent ffd3fa5
@baroquebobcat authored
View
32 Rakefile
@@ -5,12 +5,12 @@ begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "sinatra-twitter-oauth"
- gem.summary = %Q{TODO: one-line summary of your gem}
+ gem.summary = %Q{A Sinatra Extension that simplifies using twitter for login and authentication.}
gem.description = %Q{TODO: longer description of your gem}
gem.email = "ndh@baroquebobcat.com"
gem.homepage = "http://github.com/baroquebobcat/sinatra-twitter-oauth"
gem.authors = ["Nick Howard"]
- gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
+ gem.add_development_dependency "rspec", ">= 1.2.9"
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
end
Jeweler::GemcutterTasks.new
@@ -18,29 +18,21 @@ rescue LoadError
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
end
-require 'rake/testtask'
-Rake::TestTask.new(:test) do |test|
- test.libs << 'lib' << 'test'
- test.pattern = 'test/**/test_*.rb'
- test.verbose = true
+require 'spec/rake/spectask'
+Spec::Rake::SpecTask.new(:spec) do |spec|
+ spec.libs << 'lib' << 'spec'
+ spec.spec_files = FileList['spec/**/*_spec.rb']
end
-begin
- require 'rcov/rcovtask'
- Rcov::RcovTask.new do |test|
- test.libs << 'test'
- test.pattern = 'test/**/test_*.rb'
- test.verbose = true
- end
-rescue LoadError
- task :rcov do
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
- end
+Spec::Rake::SpecTask.new(:rcov) do |spec|
+ spec.libs << 'lib' << 'spec'
+ spec.pattern = 'spec/**/*_spec.rb'
+ spec.rcov = true
end
-task :test => :check_dependencies
+task :spec => :check_dependencies
-task :default => :test
+task :default => :spec
require 'rake/rdoctask'
Rake::RDocTask.new do |rdoc|
View
70 lib/sinatra-twitter-oauth.rb
@@ -0,0 +1,70 @@
+require 'sinatra/base'
+require 'twitter_oauth'
+
+require 'sinatra-twitter-oauth/twitter_oauth_ext'
+require 'sinatra-twitter-oauth/helpers'
+#Sinatra::TwitterOAuth
+#
+# A sinatra extension that abstracts away most of
+# using twitter oauth for login
+#
+#twitter_oauth_config
+#options
+# key -- oauth consumer key
+# secret -- oauth consumer secret
+# callback -- oauth callback url. Must be absolute. e.g. http://example.com/auth
+# login_template -- a single entry hash with the engine as the key e.g. :login_template => {:haml => :login}
+module Sinatra
+ module TwitterOAuth
+
+ DEFAULT_CONFIG = {
+ :key => 'changeme',
+ :secret => 'changeme',
+ :callback => 'changeme',
+ :login_template => {:text=>'<a href="/connect">Login using Twitter</a>'}
+ }
+
+ def self.registered app
+
+ app.helpers Helpers
+ app.enable :sessions
+ app.set :twitter_oauth_config, DEFAULT_CONFIG
+
+ app.get '/login' do
+ redirect '/' if @user
+
+ login_config = options.twitter_oauth_config[:login_template]
+
+ engine = login_config.keys.first
+
+ case engine
+ when :text
+ login_config[:text]
+ else
+ render engine, login_config[engine]
+ end
+ end
+
+ app.get '/connect' do
+ redirect_to_twitter_auth_url
+ end
+
+ app.get '/auth' do
+ if authenticate!
+ redirect '/'
+ else
+ status 403
+ 'Not Authenticated'
+ end
+ end
+
+ app.get '/logout' do
+ clear_oauth_session
+ redirect '/login'
+ end
+ end
+
+ end
+
+ register TwitterOAuth
+end
View
78 lib/sinatra-twitter-oauth/helpers.rb
@@ -0,0 +1,78 @@
+module Sinatra::TwitterOAuth
+ module Helpers
+
+ def login_required
+ setup_client
+
+ @user = ::TwitterOAuth::User.new(@client, session[:user]) if session[:user]
+
+ @rate_limit_status = @client.rate_limit_status
+
+ redirect '/login' unless @user
+ end
+
+ def setup_client
+ @client ||= ::TwitterOAuth::Client.new(
+ :consumer_secret => options.twitter_oauth_config[:secret],
+ :consumer_key => options.twitter_oauth_config[:key],
+ :token => session[:access_token],
+ :secret => session[:secret_token]
+ )
+ end
+
+ def get_request_token
+ setup_client
+
+ begin
+ @client.authentication_request_token(:oauth_callback=>options.twitter_oauth_config[:callback])
+ rescue StandardError => e
+ halt 500,'check your key & secret'
+ end
+ end
+
+ def get_access_token
+ setup_client
+
+ begin
+ @client.authorize(
+ session[:request_token],
+ session[:request_token_secret],
+ :oauth_verifier => params[:oauth_verifier]
+ )
+ rescue OAuth::Unauthorized => e
+ nil
+ end
+ end
+
+ def redirect_to_twitter_auth_url
+ request_token = get_request_token
+
+ session[:request_token] = request_token.token
+ session[:request_token_secret]= request_token.secret
+
+ redirect request_token.authorize_url.gsub('authorize','authenticate')
+ end
+
+ def authenticate!
+ access_token = get_access_token
+
+ if @client.authorized?
+ session[:access_token] = access_token.token
+ session[:secret_token] = access_token.secret
+ session[:user] = @client.info
+
+ session[:user]
+ else
+ nil
+ end
+ end
+
+ def clear_oauth_session
+ session[:user] = nil
+ session[:request_token] = nil
+ session[:request_token_secret] = nil
+ session[:access_token] = nil
+ session[:secret_token] = nil
+ end
+ end
+end
View
79 lib/sinatra-twitter-oauth/twitter_oauth_ext.rb
@@ -0,0 +1,79 @@
+
+#
+# Some additional domain model classes for twitter oauth.
+#
+module TwitterOAuth
+
+ class User
+ attr_accessor :client,:info
+
+ def initialize client,info
+ self.client = client
+ self.info = info
+ end
+
+ def lists
+ client.get_lists(screen_name)['lists'].map {|list| List.new client, list}
+ end
+
+ def list list_name
+ List.new client, client.get_list(screen_name, list_name)
+ end
+
+ def new_list list_name,options={}
+ List.new client, client.create_list(screen_name, list_name, options)
+ end
+
+ def destroy_list list_name
+ client.delete_list screen_name, list_name
+ end
+
+ def method_missing method, *args
+ info[method.to_s]
+ end
+ end
+
+
+ class List
+
+ attr_accessor :client,:info
+
+ #params:
+ # client: instance of TwitterOAuth::Client
+ # info: the result of client.get_list
+ def initialize client,info
+ self.info = info
+ self.client = client
+ end
+
+ def add_member screen_name
+ client.add_member_to_list user['screen_name'],slug, client.show(screen_name)["id"]
+ end
+
+ def add_members screen_names
+ screen_names.each {|name| add_member name }
+ end
+
+ def remove_member screen_name
+ client.remove_member_from_list user['screen_name'],slug, client.show(screen_name)["id"]
+ end
+
+ def remove_members screen_names
+ screen_names.each {|name| remove_member name }
+ end
+
+ def members
+ client.list_members(user['screen_name'], slug)['users'].map{|user| User.new(client,user)}
+ end
+
+ def private?
+ mode == 'private'
+ end
+
+ def method_missing method, *args
+ info[method.to_s]
+ end
+
+ end
+end
+
View
99 spec/sinatra-twitter-oauth_spec.rb
@@ -0,0 +1,99 @@
+require 'spec_helper'
+
+class TestApp < Sinatra::Base
+ register Sinatra::TwitterOAuth
+
+ get '/' do
+ login_required
+ 'hello world'
+ end
+end
+
+describe Sinatra::TwitterOAuth do
+
+ def app
+ TestApp
+ end
+
+ before do
+ @client=mock('client',
+ :rate_limit_status=>{
+ "remaining_hits"=>150,
+ "hourly_limit"=>150,
+ "reset_time_in_seconds"=>0,
+ "reset_time"=>"Sat Jan 01 00:00:00 UTC 2000"
+ })
+ TwitterOAuth::Client.stub!(:new).and_return(
+ @client=mock('client',
+ :rate_limit_status=>{"remaining_hits"=>150,"hourly_limit"=>150,"reset_time_in_seconds"=>0,"reset_time"=>"Sat Jan 01 00:00:00 UTC 2000"}))
+
+ TwitterOAuth::User.stub!(:new).and_return(@user = mock('user'))
+
+ @authed_session = {'rack.session'=>{:user => {'screen_name'=>'tester'}}}
+ end
+
+ describe 'protected by login_required' do
+ it 'redirects to /login when unauthenticated' do
+ get '/'
+ last_response.should be_redirect
+ last_response.location.should == '/login'
+ end
+
+ it 'lets you through if you are authed' do
+ @user.stub!(:lists).and_return [mock('list',:null_object=>true)]
+ get '/',{},@authed_session
+ last_response.location.should be_nil
+ last_response.should be_ok
+ end
+ end
+
+ describe 'GET /login' do
+ it 'is never redirected' do
+ get '/login'
+ last_response.location.should be_nil
+ last_response.should be_ok
+ end
+ end
+
+
+ describe 'GET /connect' do
+ it 'gets a request token' do
+ @client.should_receive(:authentication_request_token).and_return(mock('request token',:authorize_url=>'http://example.com',:token=>'token',:secret=>'secret'))
+ get '/connect'
+ end
+ it "redirects to the request token's auth url" do
+ @client.stub!(:authentication_request_token).and_return(token = mock('request token',:token=>'token',:secret=>'secret'))
+ token.should_receive(:authorize_url).and_return 'http://example.com'
+ get '/connect'
+ last_response.location.should == 'http://example.com'
+ end
+ end
+
+ describe 'GET /auth' do
+ describe "on auth denied" do
+ it "responds with 'Not Authenticated' and a 403" do
+ @client.stub!(:authorize).and_raise OAuth::Unauthorized.new
+ @client.stub!(:authorized?).and_return false
+ get '/auth'
+ last_response.status.should == 403
+ last_response.body.should == 'Not Authenticated'
+ end
+ end
+ describe 'on auth success' do
+ it "redirects to '/'" do
+ @client.stub!(:authorize).and_return(mock('access token',:null_object => true))
+ @client.stub!(:authorized?).and_return true
+ @client.stub!(:info).and_return(mock(:user))
+ get '/auth'
+ last_response.location.should == '/'
+ end
+ end
+ end
+
+ describe "GET /logout" do
+ it "redirects to /login" do
+ get '/logout',{},@authed_session
+ last_response.location.should == '/login'
+ end
+ end
+end
View
10 spec/spec_helper.rb
@@ -0,0 +1,10 @@
+ENV['RACK_ENV'] = 'test'
+require 'rubygems'
+
+require File.expand_path('../lib/sinatra-twitter-oauth', File.dirname(__FILE__))
+
+require 'spec'
+require 'spec/interop/test'
+require 'rack/test'
+
+Test::Unit::TestCase.send :include, Rack::Test::Methods
View
10 test/helper.rb
@@ -1,10 +0,0 @@
-require 'rubygems'
-require 'test/unit'
-require 'shoulda'
-
-$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
-$LOAD_PATH.unshift(File.dirname(__FILE__))
-require 'sinatra-twitter-oauth'
-
-class Test::Unit::TestCase
-end
View
7 test/test_sinatra-twitter-oauth.rb
@@ -1,7 +0,0 @@
-require 'helper'
-
-class TestSinatraTwitterOauth < Test::Unit::TestCase
- should "probably rename this file and start testing for real" do
- flunk "hey buddy, you should probably rename this file and start testing for real"
- end
-end

0 comments on commit 1d43750

Please sign in to comment.
Something went wrong with that request. Please try again.