diff --git a/Gemfile b/Gemfile index e21f780ac..bcafd1743 100644 --- a/Gemfile +++ b/Gemfile @@ -19,6 +19,8 @@ gem 'devise_invitable', '0.5.0' gem 'omniauth', '0.2.6' gem 'twitter', '1.5.0' +gem 'oauth2-provider', '~> 0.0.0' + #Views gem 'haml', '3.0.25' gem 'will_paginate', '3.0.pre2' @@ -91,4 +93,8 @@ group :test do gem 'mongrel', :require => false if RUBY_VERSION.include? '1.8' gem 'rspec-instafail', '>= 0.1.7', :require => false gem 'fuubar' + + #For Chubbies + gem 'sinatra', :require => false + gem 'httparty', :require => false end diff --git a/Gemfile.lock b/Gemfile.lock index 502d9d96e..e3d15cfb8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -153,7 +153,7 @@ GEM faraday (0.6.1) addressable (~> 2.2.4) multipart-post (~> 1.1.0) - rack (>= 1.1.0, < 2) + rack (< 2, >= 1.1.0) faraday_middleware (0.6.3) faraday (~> 0.6.0) fastercsv (1.5.4) @@ -183,6 +183,8 @@ GEM hashie (1.0.0) highline (1.6.2) http_connection (1.4.1) + httparty (0.7.4) + crack (= 0.1.8) i18n (0.6.0) i18n-inflector (2.5.1) i18n (>= 0.4.1) @@ -267,6 +269,9 @@ GEM oauth2 (0.4.1) faraday (~> 0.6.1) multi_json (>= 0.0.5) + oauth2-provider (0.0.16) + activesupport (~> 3.0.1) + addressable (~> 2.2) ohai (0.5.8) extlib json (<= 1.4.6, >= 1.4.4) @@ -421,6 +426,7 @@ DEPENDENCIES fuubar haml (= 3.0.25) http_accept_language! + httparty i18n-inflector-rails (~> 1.0) jammit (= 0.5.4) jasmine (= 1.0.2.1) @@ -431,6 +437,7 @@ DEPENDENCIES mysql2 (= 0.2.6) newrelic_rpm nokogiri + oauth2-provider (~> 0.0.0) ohai (= 0.5.8) omniauth (= 0.2.6) rails (= 3.0.3) @@ -445,6 +452,7 @@ DEPENDENCIES ruby-debug selenium-webdriver (= 0.1.3) settingslogic (= 2.0.6) + sinatra sod! thin (= 1.2.11) twitter (= 1.5.0) diff --git a/app/controllers/apis_controller.rb b/app/controllers/apis_controller.rb index 4bad3f232..5ed3ed5df 100644 --- a/app/controllers/apis_controller.rb +++ b/app/controllers/apis_controller.rb @@ -1,115 +1,15 @@ -class ApisController < ApplicationController #We should start with this versioned, V0ApisController BEES - before_filter :authenticate_user!, :only => [:home_timeline] +class ApisController < ApplicationController + authenticate_with_oauth + before_filter :set_user_from_oauth respond_to :json - #posts - def public_timeline - set_defaults - timeline = StatusMessage.where(:public => true).includes(:photos, :author => :profile).paginate(:page => params[:page], :per_page => params[:per_page], :order => "#{params[:order]} DESC") - respond_with timeline do |format| - format.json{ render :json => timeline.to_json(:format => :twitter) } - end + def me + @person = @user.person + render :json => {:birthday => @person.profile.birthday, :name => @person.name} end - def user_timeline - set_defaults - - if person = Person.where(:guid => params[:user_id]).first - if user_signed_in? - timeline = current_user.posts_from(person) - else - timeline = StatusMessage.where(:public => true, :author_id => person.id).includes(:photos).paginate(:page => params[:page], :per_page => params[:per_page], :order => "#{params[:order]} DESC") - end - respond_with timeline do |format| - format.json{ render :json => timeline.to_json(:format => :twitter) } - end - else - render :json => {:status => 'failed', :reason => 'user not found'}, :status => 404 - end - end - - def home_timeline - set_defaults - timeline = current_user.visible_posts(:max_time => params[:max_time], - :limit => params[:per_page], - :order => "#{params[:order]} DESC").includes(:comments, :photos, :likes, :dislikes) - respond_with timeline do |format| - format.json{ render :json => timeline.to_json(:format => :twitter) } - end - end - - def statuses - status = StatusMessage.where(:guid => params[:guid], :public => true).includes(:photos, :author => :profile).first - if status - respond_with status do |format| - format.json{ render :json => status.to_json(:format => :twitter) } - end - else - render(:nothing => true, :status => 404) - end - end - - #people - def users - if params[:user_id] - person = Person.where(:guid => params[:user_id]).first - elsif params[:screen_name] - person = Person.where(:diaspora_handle => params[:screen_name]).first - end - - if person && !person.remote? - respond_with person do |format| - format.json{ render :json => person.to_json(:format => :twitter) } - end - else - render(:nothing => true, :status => 404) - end - end - - def users_search - set_defaults - - if params[:q] - people = Person.public_search(params[:q]).paginate(:page => params[:page], :per_page => params[:per_page], :order => "#{params[:order]} DESC") - end - - if people - respond_with people do |format| - format.json{ render :json => people.to_json(:format => :twitter) } - end - else - render(:nothing => true, :status => 404) - end - end - - def users_profile_image - if person = Person.where(:diaspora_handle => params[:screen_name]).first - redirect_to person.profile.image_url - else - render(:nothing => true, :status => 404) - end - end - - #tags - def tag_posts - set_defaults - posts = StatusMessage.where(:public => true, :pending => false) - posts = posts.tagged_with(params[:tag]) - posts = posts.includes(:comments, :photos).paginate(:page => params[:page], :per_page => params[:per_page], :order => "#{params[:order]} DESC") - render :json => posts.as_json(:format => :twitter) - end - - def tag_people - set_defaults - profiles = Profile.tagged_with(params[:tag]).where(:searchable => true).select('profiles.id, profiles.person_id') - people = Person.where(:id => profiles.map{|p| p.person_id}).paginate(:page => params[:page], :per_page => params[:per_page], :order => "#{params[:order]} DESC") - render :json => people.as_json(:format => :twitter) - end - - protected - def set_defaults - params[:per_page] = 20 if params[:per_page].nil? || params[:per_page] > 100 - params[:order] = 'created_at' unless ['created_at', 'updated_at'].include?(params[:order]) - params[:page] ||= 1 + private + def set_user_from_oauth + @user = request.env['oauth2'].resource_owner end end diff --git a/app/controllers/authorizations_controller.rb b/app/controllers/authorizations_controller.rb new file mode 100644 index 000000000..2b90aed5e --- /dev/null +++ b/app/controllers/authorizations_controller.rb @@ -0,0 +1,18 @@ +class AuthorizationsController < ApplicationController + include OAuth2::Provider::Rack::AuthorizationCodesSupport + before_filter :authenticate_user! + before_filter :block_invalid_authorization_code_requests + + def new + @client = oauth2_authorization_request.client + end + + def create + if params[:commit] == "Yes" + grant_authorization_code(current_user) + else + deny_authorization_code + end + end +end + diff --git a/app/models/person.rb b/app/models/person.rb index caf229ae1..ff3750150 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -192,29 +192,6 @@ class Person < ActiveRecord::Base !remote? end - def as_json(opts={}) - opts ||= {} - if(opts[:format] == :twitter) - { - :id => self.guid, - :screen_name => self.diaspora_handle, - :name => self.name, - :created_at => self.created_at, - :profile_image_url => self.profile.image_url(:thumb_small), - :profile => self.profile.as_json(opts) - } - else - {:id => self.guid, - :name => self.name, - :avatar => self.profile.image_url(:thumb_small), - :handle => self.diaspora_handle, - :url => "/people/#{self.id}"} - end - end - - def to_twitter(format=:json) - end - def has_photos? self.posts.where(:type => "Photo").exists? end diff --git a/app/models/photo.rb b/app/models/photo.rb index f39ced116..0f8118257 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -98,17 +98,6 @@ class Photo < Post true end - def as_json(opts={}) - { - :photo => { - :id => self.id, - :url => self.url, - :thumb_small => self.url(:thumb_small), - :text => self.text - } - } - end - scope :on_statuses, lambda { |post_guids| where(:status_message_guid => post_guids) } diff --git a/app/models/post.rb b/app/models/post.rb index 1edded31b..51de407ae 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -54,15 +54,6 @@ class Post < ActiveRecord::Base new_post end - def as_json(opts={}) - { - :post => { - :id => self.guid, - :author => self.author.as_json, - } - } - end - def mutable? false end diff --git a/app/models/status_message.rb b/app/models/status_message.rb index 3fb1f9b7f..abfa6b394 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -108,26 +108,6 @@ class StatusMessage < Post XML end - def as_json(opts={}) - opts ||= {} - if(opts[:format] == :twitter) - { - :id => self.guid, - :text => self.formatted_message(:plain_text => true), - :entities => { - :urls => [], - :hashtags => self.tag_list, - :user_mentions => self.mentioned_people.map{|p| p.diaspora_handle}, - }, - :source => 'diaspora', - :created_at => self.created_at, - :user => self.author.as_json(opts) - } - else - super(opts) - end - end - def socket_to_user(user_or_id, opts={}) unless opts[:aspect_ids] user_id = user_or_id.instance_of?(Fixnum) ? user_or_id : user_or_id.id diff --git a/app/views/authorizations/new.html.haml b/app/views/authorizations/new.html.haml new file mode 100644 index 000000000..d59342008 --- /dev/null +++ b/app/views/authorizations/new.html.haml @@ -0,0 +1,7 @@ += form_for :authorization, + :url => oauth_authorize_path(params.slice(:redirect_uri, :client_id, :client_secret)) do |form| + %h2 + = "Authorize #{@client.name}?" + + = form.submit "Fuck Yeah!", :value => "Yes" + = form.submit "Hell No.", :value => "No" diff --git a/config/routes.rb b/config/routes.rb index 5e21f0b2d..5a551a267 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -34,7 +34,7 @@ Diaspora::Application.routes.draw do resources :tags, :only => [:index] get 'tags/:name' => 'tags#show', :as => 'tag' - + resources :apps, :only => [:show] # Users and people @@ -68,6 +68,9 @@ Diaspora::Application.routes.draw do resources :photos, :controller => "photos", :only => [:create, :show, :destroy] end + get "/oauth/authorize" => "authorizations#new" + post "/oauth/authorize" => "authorizations#create" + #Temporary token_authenticable route resource :token, :only => [:show, :create] @@ -125,17 +128,7 @@ Diaspora::Application.routes.draw do end scope 'api/v0', :controller => :apis do - match 'statuses/public_timeline' => :public_timeline - match 'statuses/home_timeline' => :home_timeline - match 'statuses/show/:guid' => :statuses - match 'statuses/user_timeline' => :user_timeline - - match 'users/show' => :users - match 'users/search' => :users_search - match 'users/profile_image' => :users_profile_image - - match 'tags_posts/:tag' => :tag_posts - match 'tags_people/:tag' => :tag_people + get 'me' => :me end diff --git a/db/migrate/20110526184644_add_oauth2_tables.rb b/db/migrate/20110526184644_add_oauth2_tables.rb new file mode 100644 index 000000000..7d20f7418 --- /dev/null +++ b/db/migrate/20110526184644_add_oauth2_tables.rb @@ -0,0 +1,42 @@ +class AddOauth2Tables < ActiveRecord::Migration + def self.up + create_table 'oauth_clients', :force => true do |t| + t.string 'name' + t.string 'oauth_identifier', :limit => 32, :null => false + t.string 'oauth_secret', :limit => 32, :null => false + end + + create_table 'oauth_authorization_codes', :force => true do |t| + t.integer 'authorization_id', :null => false + t.string 'code', :limit => 32, :null => false + t.datetime 'expires_at' + t.datetime 'created_at' + t.datetime 'updated_at' + t.string 'redirect_uri' + end + + create_table 'oauth_authorizations', :force => true do |t| + t.integer 'client_id', :null => false + t.integer 'resource_owner_id' + t.string 'resource_owner_type', :limit => 32 + t.string 'scope' + t.datetime 'expires_at' + end + + create_table 'oauth_access_tokens', :force => true do |t| + t.integer 'authorization_id', :null => false + t.string 'access_token', :limit => 32, :null => false + t.string 'refresh_token', :limit => 32 + t.datetime 'expires_at' + t.datetime 'created_at' + t.datetime 'updated_at' + end + end + + def self.down + drop_table 'oauth_access_tokens' + drop_table 'oauth_authorizations' + drop_table 'oauth_authorization_codes' + drop_table 'oauth_clients' + end +end diff --git a/db/schema.rb b/db/schema.rb index 044cccfca..78a15252d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -195,6 +195,38 @@ ActiveRecord::Schema.define(:version => 20110603212633) do add_index "notifications", ["target_id"], :name => "index_notifications_on_target_id" add_index "notifications", ["target_type", "target_id"], :name => "index_notifications_on_target_type_and_target_id" + create_table "oauth_access_tokens", :force => true do |t| + t.integer "authorization_id", :null => false + t.string "access_token", :limit => 32, :null => false + t.string "refresh_token", :limit => 32 + t.datetime "expires_at" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "oauth_authorization_codes", :force => true do |t| + t.integer "authorization_id", :null => false + t.string "code", :limit => 32, :null => false + t.datetime "expires_at" + t.datetime "created_at" + t.datetime "updated_at" + t.string "redirect_uri" + end + + create_table "oauth_authorizations", :force => true do |t| + t.integer "client_id", :null => false + t.integer "resource_owner_id" + t.string "resource_owner_type", :limit => 32 + t.string "scope" + t.datetime "expires_at" + end + + create_table "oauth_clients", :force => true do |t| + t.string "name" + t.string "oauth_identifier", :limit => 32, :null => false + t.string "oauth_secret", :limit => 32, :null => false + end + create_table "people", :force => true do |t| t.string "guid", :null => false t.text "url", :null => false diff --git a/features/oauth.feature b/features/oauth.feature new file mode 100644 index 000000000..c3ce9a3e6 --- /dev/null +++ b/features/oauth.feature @@ -0,0 +1,29 @@ +@javascript +Feature: oauth + Exchanging oauth credentials + + Background: + Given Chubbies is running + And a user with username "bob" and password "secret" + + Scenario: Authorize Chubbies + Given Chubbies is registered on my pod + When I visit "/" on Chubbies + And I try to authorize Chubbies + Then I should see "Authorize Chubbies?" + + When I press "Yes" + Then I should be on "/account" on Chubbies + And I should see my "profile.birthday" + And I should see my "name" + + Scenario: Not authorize Chubbies + Given Chubbies is registered on my pod + When I visit "/" on Chubbies + And I try to authorize Chubbies + Then I should see "Authorize Chubbies?" + + When I press "No" + Then I should be on "/callback" on Chubbies + Then I should see "What is your major malfunction?" + diff --git a/features/step_definitions/oauth_steps.rb b/features/step_definitions/oauth_steps.rb new file mode 100644 index 000000000..bc219be12 --- /dev/null +++ b/features/step_definitions/oauth_steps.rb @@ -0,0 +1,70 @@ +Given /^Chubbies is running$/ do + if Chubbies.running? + puts "Chubbies is already running. Killing it." + Chubbies.kill + end + Chubbies.run + at_exit do + Chubbies.kill + end +end + +Given /^Chubbies is registered on my pod$/ do + OAuth2::Provider.client_class.create! :name => 'Chubbies', + :oauth_identifier => 'abcdefgh12345678', + :oauth_secret => 'secret' +end + +And /^I should see my "([^"]+)"/ do |code| + page.should have_content(@me.person.instance_eval(code).to_s) +end + +When /^I try to authorize Chubbies$/ do + And 'I follow "Log in with Diaspora"' + Then 'I should be on the new user session page' + And "I fill in \"Username\" with \"#{@me.username}\"" + And "I fill in \"Password\" with \"#{@me.password}\"" + And 'I press "Sign in"' + Then 'I should be on the oauth authorize page' +end + +When /^I visit "([^"]+)" on Chubbies$/ do |path| + former_host = Capybara.app_host + Capybara.app_host = "localhost:#{Chubbies::PORT}" + visit(path) + Capybara.app_host = former_host +end + +class Chubbies + PORT = 9292 + + def self.run + @pid = fork do + Process.exec "cd #{Rails.root}/spec/support/chubbies/ && DIASPORA_PORT=9887 bundle exec rackup -p #{PORT} 2> /dev/null" + end + while(!running?) do + sleep(1) + end + end + + def self.kill + `kill -9 #{get_pid}` + end + + def self.running? + begin + RestClient.get("localhost:#{PORT}") + true + rescue Errno::ECONNREFUSED + false + end + end + + def self.get_pid + @pid ||= lambda { + processes = `ps -ax -o pid,command | grep "rackup -p #{PORT}"`.split("\n") + processes = processes.select{|p| !p.include?("grep") } + processes.first.split(" ").first + }.call + end +end diff --git a/features/step_definitions/user_steps.rb b/features/step_definitions/user_steps.rb index f327e463e..dd142f133 100644 --- a/features/step_definitions/user_steps.rb +++ b/features/step_definitions/user_steps.rb @@ -3,6 +3,7 @@ Given /^a user with username "([^\"]*)" and password "([^\"]*)"$/ do |username, :password_confirmation => password, :getting_started => false) @me.aspects.create(:name => "Besties") @me.aspects.create(:name => "Unicorns") + @me.reload end Given /^that I am a rock star$/ do diff --git a/spec/controllers/apis_controller_spec.rb b/spec/controllers/apis_controller_spec.rb index 3dcb7cd65..d5d798ba2 100644 --- a/spec/controllers/apis_controller_spec.rb +++ b/spec/controllers/apis_controller_spec.rb @@ -5,223 +5,4 @@ require 'spec_helper' describe ApisController do - before do - @status_message1 = Factory(:status_message, :text => '#bobby #flay #sux', :public => true, :updated_at => Time.now + 20) - - @status_message2 = Factory(:status_message, :text => '#aobby', :public => true, :created_at => Time.now + 10) - @status_message3 = Factory(:status_message, :created_at => Time.now + 15) - @person = Factory(:person, :profile => Factory.build(:profile,:first_name => 'bobby', :searchable => true, :tag_string => '#zord')) - @person.profile.save - end - - describe '#public_timeline' do - it 'returns all of the public posts' do - get :public_timeline, :format => :json - @posts = JSON.parse(response.body) - @posts.map{|p| p['id']}.should == [@status_message2.guid, @status_message1.guid] - @posts.count.should == 2 - end - - it 'accepts an order paramater' do - get :public_timeline, :format => :json, :order => 'updated_at' - @posts = JSON.parse(response.body) - @posts.map{|p| p['id']}.should == [@status_message1.guid, @status_message2.guid] - end - - it 'does not allow arbitrary orders' do - get :public_timeline, :format => :json, :order => 'text' - @posts = JSON.parse(response.body) - @posts.map{|p| p['id']}.should == [@status_message2.guid, @status_message1.guid] - end - - it 'accepts a page paramater' do - get :public_timeline, :format => :json, :per_page=> 1, :page => 2 - JSON.parse(response.body).first['id'].should == @status_message1.guid - end - - it 'accepts a per_page param' do - get :public_timeline, :format => :json, :per_page=> 1 - JSON.parse(response.body).count.should == 1 - end - end - - context 'protected timelines' do - let(:authenticate){ - sign_in(:user, @user); - @controller.stub(:current_user).and_return(@user) - } - - before do - @message1 = alice.post(:status_message, :text=> "hello", :to => alice.aspects.first) - @message2 = eve.post(:status_message, :text=> "hello", :to => eve.aspects.first) - end - - describe '#home_timeline' do - it 'authenticates' do - get :home_timeline, :format => :json - response.code.should == '401' - end - - it 'shows posts for alice' do - @user = alice - authenticate - - get :home_timeline, :format => :json - p = JSON.parse(response.body) - - p.length.should == 1 - p[0]['id'].should == @message1.guid - end - - it 'shows posts for eve' do - @user = eve - authenticate - - get :home_timeline, :format => :json - p = JSON.parse(response.body) - - p.length.should == 1 - p[0]['id'].should == @message2.guid - end - - it 'shows posts for bob' do - @user = bob - authenticate - - get :home_timeline, :format => :json - p = JSON.parse(response.body) - - p.length.should == 2 - end - end - - describe '#user_timeline' do - context 'unauthenticated' do - it 'shows public posts' do - get :user_timeline, :format => :json, :user_id => @status_message1.author.guid - posts = JSON.parse(response.body) - posts.first['id'].should == @status_message1.guid - posts.length.should == 1 - end - it 'does not show non-public posts' do - get :user_timeline, :format => :json, :user_id => alice.person.guid - posts = JSON.parse(response.body) - posts.should be_empty - end - end - context 'authenticated' do - context 'with bob logged in' do - before do - @user = bob - authenticate - end - - it 'shows alice' do - get :user_timeline, :format => :json, :user_id => alice.person.guid - p = JSON.parse(response.body) - - p.length.should == 1 - p[0]['id'].should == @message1.guid - end - - it 'shows eve' do - get :user_timeline, :format => :json, :user_id => eve.person.guid - p = JSON.parse(response.body) - - p.length.should == 1 - p[0]['id'].should == @message2.guid - end - - it 'shows bob' do - get :user_timeline, :format => :json, :user_id => bob.person.guid - p = JSON.parse(response.body) - p.length.should == 0 - end - end - - context 'with alice logged in' do - before do - @user = alice - authenticate - end - - it 'shows alice' do - get :user_timeline, :format => :json, :user_id => alice.person.guid - p = JSON.parse(response.body) - - p.length.should == 1 - p[0]['id'].should == @message1.guid - end - - it 'shows eve' do - get :user_timeline, :format => :json, :user_id => eve.person.guid - p = JSON.parse(response.body) - p.length.should == 0 - end - end - end - end - end - - describe '#users_profile_image' do - it 'redirects on success' do - get :users_profile_image, :screen_name => bob.diaspora_handle, :format => :json - response.should redirect_to(bob.person.profile.image_url) - end - end - - describe '#statuses' do - it 'returns a post' do - get :statuses, :guid => @status_message1.guid, :format => :json - p = JSON.parse(response.body) - p['id'].should == @status_message1.guid - p['text'].should == @status_message1.formatted_message(:plain_text => true) - p['entities'].class.should == Hash - p['source'].should == 'diaspora' - p['user'].should == JSON.parse(@status_message1.author.to_json(:format => :twitter)) - p['created_at'].should_not be_nil - end - - it 'returns a 404 if does not exsist' do - get :statuses, :guid => '999' - response.code.should == '404' - end - end - - describe '#users' do - it 'succeeds' do - get :users, :user_id => alice.person.guid, :format => :json - p = JSON.parse(response.body) - p['id'].should == alice.person.guid - p['name'].should == alice.person.name - p['screen_name'].should == alice.person.diaspora_handle - p['profile_image_url'].should == alice.person.profile.image_url(:thumb_small) - p['created_at'].should_not be_nil - end - end - - describe '#users_search' do - it 'searches' do - get :users_search, :q => @person.name, :format => :json - p = JSON.parse(response.body) - response.code.should == '200' - end - end - - describe '#tag_posts' do - it 'succeeds' do - get :tag_posts, :tag => 'flay' - p = JSON.parse(response.body).first - p['id'].should == @status_message1.guid - p['user']['id'].should == @status_message1.author.guid - end - end - - describe '#tag_people' do - it 'succeeds' do - get :tag_people, :tag => 'zord' - p = JSON.parse(response.body).first - p['id'].should == @person.guid - end - end end diff --git a/spec/factories.rb b/spec/factories.rb index db83249dc..9dc44722c 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -14,6 +14,7 @@ end Factory.define :profile do |p| p.sequence(:first_name) { |n| "Robert#{n}#{r_str}" } p.sequence(:last_name) { |n| "Grimm#{n}#{r_str}" } + p.birthday Date.today end diff --git a/spec/support/chubbies/Gemfile b/spec/support/chubbies/Gemfile new file mode 100644 index 000000000..42d3861db --- /dev/null +++ b/spec/support/chubbies/Gemfile @@ -0,0 +1,6 @@ +source :rubygems + +gem 'sinatra' +gem 'haml' + +gem 'httparty' \ No newline at end of file diff --git a/spec/support/chubbies/Gemfile.lock b/spec/support/chubbies/Gemfile.lock new file mode 100644 index 000000000..3e1dd9371 --- /dev/null +++ b/spec/support/chubbies/Gemfile.lock @@ -0,0 +1,20 @@ +GEM + remote: http://rubygems.org/ + specs: + crack (0.1.8) + haml (3.0.18) + httparty (0.7.4) + crack (= 0.1.8) + rack (1.2.2) + sinatra (1.2.6) + rack (~> 1.1) + tilt (>= 1.2.2, < 2.0) + tilt (1.3) + +PLATFORMS + ruby + +DEPENDENCIES + haml + httparty + sinatra diff --git a/spec/support/chubbies/README b/spec/support/chubbies/README new file mode 100644 index 000000000..34f933def --- /dev/null +++ b/spec/support/chubbies/README @@ -0,0 +1,8 @@ +This is a (very very) simple OAuth2 client, designed to work with the Diaspora tests. To get it running, cd to the client folder, then run: + +1) bundle install +2) bundle exec rackup + +This should start the client on port 9292 + +Assuming an example server is running (such as the one in examples/rails3-example), visit http://localhost:9292. To read content from the server you'll be asked to login (tomafro/secret) and then authorize the client. Finally some very simple content from the server will be shown. diff --git a/spec/support/chubbies/app.rb b/spec/support/chubbies/app.rb new file mode 100644 index 000000000..33e1ef2ef --- /dev/null +++ b/spec/support/chubbies/app.rb @@ -0,0 +1,75 @@ +require 'rubygems' +require 'bundler/setup' +require 'sinatra' +require 'haml' +require 'httparty' + +def resource_host + url = "http://localhost:" + if ENV["DIASPORA_PORT"] + url << ENV["DIASPORA_PORT"] + else + url << "3000" + end + url +end + +CLIENT_ID = 'abcdefgh12345678' +CLIENT_SECRET = 'secret' +RESOURCE_HOST = resource_host + +enable :sessions + +helpers do + def redirect_uri + "http://" + request.host_with_port + "/callback" + end + + def access_token + session[:access_token] + end + + def get_with_access_token(path) + HTTParty.get(RESOURCE_HOST + path, :query => {:oauth_token => access_token}) + end + + def authorize_url + RESOURCE_HOST + "/oauth/authorize?client_id=#{CLIENT_ID}&client_secret=#{CLIENT_SECRET}&redirect_uri=#{redirect_uri}" + end + + def access_token_url + RESOURCE_HOST + "/oauth/access_token" + end +end + +get '/' do + haml :home +end + +get '/callback' do + unless params["error"] + response = HTTParty.post(access_token_url, :body => { + :client_id => CLIENT_ID, + :client_secret => CLIENT_SECRET, + :redirect_uri => redirect_uri, + :code => params["code"], + :grant_type => 'authorization_code'} + ) + + session[:access_token] = response["access_token"] + redirect '/account' + else + "What is your major malfunction?" + end +end + +get '/account' do + if access_token + @resource_server = RESOURCE_HOST + @url = "/api/v0/me.json" + @resource_response = get_with_access_token(@url) + haml :response + else + redirect authorize_url + end +end diff --git a/spec/support/chubbies/config.ru b/spec/support/chubbies/config.ru new file mode 100644 index 000000000..7ba7d1acb --- /dev/null +++ b/spec/support/chubbies/config.ru @@ -0,0 +1,3 @@ +require 'app' + +run Sinatra::Application \ No newline at end of file diff --git a/spec/support/chubbies/views/home.haml b/spec/support/chubbies/views/home.haml new file mode 100644 index 000000000..3b5832e08 --- /dev/null +++ b/spec/support/chubbies/views/home.haml @@ -0,0 +1,2 @@ +%a{:href => '/account'} + Log in with Diaspora diff --git a/spec/support/chubbies/views/response.haml b/spec/support/chubbies/views/response.haml new file mode 100644 index 000000000..c5237687e --- /dev/null +++ b/spec/support/chubbies/views/response.haml @@ -0,0 +1,13 @@ +%div + The response from #{@resource_server} at path #{@url}: + + %h2 + Headers + %pre + =@resource_response.headers.inspect + + %h2 + Body + %pre + =@resource_response.body.inspect +