Add Chubbies, the oauth sample app, and a cucumber feature for part of an oauth flow

This commit is contained in:
Raphael Sofaer 2011-05-26 17:46:21 -07:00 committed by Maxwell Salzberg
parent 8841f62cf0
commit 381b85189d
24 changed files with 356 additions and 404 deletions

View file

@ -19,6 +19,8 @@ gem 'devise_invitable', '0.5.0'
gem 'omniauth', '0.2.6' gem 'omniauth', '0.2.6'
gem 'twitter', '1.5.0' gem 'twitter', '1.5.0'
gem 'oauth2-provider', '~> 0.0.0'
#Views #Views
gem 'haml', '3.0.25' gem 'haml', '3.0.25'
gem 'will_paginate', '3.0.pre2' gem 'will_paginate', '3.0.pre2'
@ -91,4 +93,8 @@ group :test do
gem 'mongrel', :require => false if RUBY_VERSION.include? '1.8' gem 'mongrel', :require => false if RUBY_VERSION.include? '1.8'
gem 'rspec-instafail', '>= 0.1.7', :require => false gem 'rspec-instafail', '>= 0.1.7', :require => false
gem 'fuubar' gem 'fuubar'
#For Chubbies
gem 'sinatra', :require => false
gem 'httparty', :require => false
end end

View file

@ -153,7 +153,7 @@ GEM
faraday (0.6.1) faraday (0.6.1)
addressable (~> 2.2.4) addressable (~> 2.2.4)
multipart-post (~> 1.1.0) multipart-post (~> 1.1.0)
rack (>= 1.1.0, < 2) rack (< 2, >= 1.1.0)
faraday_middleware (0.6.3) faraday_middleware (0.6.3)
faraday (~> 0.6.0) faraday (~> 0.6.0)
fastercsv (1.5.4) fastercsv (1.5.4)
@ -183,6 +183,8 @@ GEM
hashie (1.0.0) hashie (1.0.0)
highline (1.6.2) highline (1.6.2)
http_connection (1.4.1) http_connection (1.4.1)
httparty (0.7.4)
crack (= 0.1.8)
i18n (0.6.0) i18n (0.6.0)
i18n-inflector (2.5.1) i18n-inflector (2.5.1)
i18n (>= 0.4.1) i18n (>= 0.4.1)
@ -267,6 +269,9 @@ GEM
oauth2 (0.4.1) oauth2 (0.4.1)
faraday (~> 0.6.1) faraday (~> 0.6.1)
multi_json (>= 0.0.5) multi_json (>= 0.0.5)
oauth2-provider (0.0.16)
activesupport (~> 3.0.1)
addressable (~> 2.2)
ohai (0.5.8) ohai (0.5.8)
extlib extlib
json (<= 1.4.6, >= 1.4.4) json (<= 1.4.6, >= 1.4.4)
@ -421,6 +426,7 @@ DEPENDENCIES
fuubar fuubar
haml (= 3.0.25) haml (= 3.0.25)
http_accept_language! http_accept_language!
httparty
i18n-inflector-rails (~> 1.0) i18n-inflector-rails (~> 1.0)
jammit (= 0.5.4) jammit (= 0.5.4)
jasmine (= 1.0.2.1) jasmine (= 1.0.2.1)
@ -431,6 +437,7 @@ DEPENDENCIES
mysql2 (= 0.2.6) mysql2 (= 0.2.6)
newrelic_rpm newrelic_rpm
nokogiri nokogiri
oauth2-provider (~> 0.0.0)
ohai (= 0.5.8) ohai (= 0.5.8)
omniauth (= 0.2.6) omniauth (= 0.2.6)
rails (= 3.0.3) rails (= 3.0.3)
@ -445,6 +452,7 @@ DEPENDENCIES
ruby-debug ruby-debug
selenium-webdriver (= 0.1.3) selenium-webdriver (= 0.1.3)
settingslogic (= 2.0.6) settingslogic (= 2.0.6)
sinatra
sod! sod!
thin (= 1.2.11) thin (= 1.2.11)
twitter (= 1.5.0) twitter (= 1.5.0)

View file

@ -1,115 +1,15 @@
class ApisController < ApplicationController #We should start with this versioned, V0ApisController BEES class ApisController < ApplicationController
before_filter :authenticate_user!, :only => [:home_timeline] authenticate_with_oauth
before_filter :set_user_from_oauth
respond_to :json respond_to :json
#posts def me
def public_timeline @person = @user.person
set_defaults render :json => {:birthday => @person.profile.birthday, :name => @person.name}
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
end end
def user_timeline private
set_defaults def set_user_from_oauth
@user = request.env['oauth2'].resource_owner
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
end end
end end

View file

@ -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

View file

@ -192,29 +192,6 @@ class Person < ActiveRecord::Base
!remote? !remote?
end 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? def has_photos?
self.posts.where(:type => "Photo").exists? self.posts.where(:type => "Photo").exists?
end end

View file

@ -98,17 +98,6 @@ class Photo < Post
true true
end 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| scope :on_statuses, lambda { |post_guids|
where(:status_message_guid => post_guids) where(:status_message_guid => post_guids)
} }

View file

@ -54,15 +54,6 @@ class Post < ActiveRecord::Base
new_post new_post
end end
def as_json(opts={})
{
:post => {
:id => self.guid,
:author => self.author.as_json,
}
}
end
def mutable? def mutable?
false false
end end

View file

@ -108,26 +108,6 @@ class StatusMessage < Post
XML XML
end 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={}) def socket_to_user(user_or_id, opts={})
unless opts[:aspect_ids] unless opts[:aspect_ids]
user_id = user_or_id.instance_of?(Fixnum) ? user_or_id : user_or_id.id user_id = user_or_id.instance_of?(Fixnum) ? user_or_id : user_or_id.id

View file

@ -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"

View file

@ -68,6 +68,9 @@ Diaspora::Application.routes.draw do
resources :photos, :controller => "photos", :only => [:create, :show, :destroy] resources :photos, :controller => "photos", :only => [:create, :show, :destroy]
end end
get "/oauth/authorize" => "authorizations#new"
post "/oauth/authorize" => "authorizations#create"
#Temporary token_authenticable route #Temporary token_authenticable route
resource :token, :only => [:show, :create] resource :token, :only => [:show, :create]
@ -125,17 +128,7 @@ Diaspora::Application.routes.draw do
end end
scope 'api/v0', :controller => :apis do scope 'api/v0', :controller => :apis do
match 'statuses/public_timeline' => :public_timeline get 'me' => :me
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
end end

View file

@ -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

View file

@ -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_id"], :name => "index_notifications_on_target_id"
add_index "notifications", ["target_type", "target_id"], :name => "index_notifications_on_target_type_and_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| create_table "people", :force => true do |t|
t.string "guid", :null => false t.string "guid", :null => false
t.text "url", :null => false t.text "url", :null => false

29
features/oauth.feature Normal file
View file

@ -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?"

View file

@ -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

View file

@ -3,6 +3,7 @@ Given /^a user with username "([^\"]*)" and password "([^\"]*)"$/ do |username,
:password_confirmation => password, :getting_started => false) :password_confirmation => password, :getting_started => false)
@me.aspects.create(:name => "Besties") @me.aspects.create(:name => "Besties")
@me.aspects.create(:name => "Unicorns") @me.aspects.create(:name => "Unicorns")
@me.reload
end end
Given /^that I am a rock star$/ do Given /^that I am a rock star$/ do

View file

@ -5,223 +5,4 @@
require 'spec_helper' require 'spec_helper'
describe ApisController do 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 end

View file

@ -14,6 +14,7 @@ end
Factory.define :profile do |p| Factory.define :profile do |p|
p.sequence(:first_name) { |n| "Robert#{n}#{r_str}" } p.sequence(:first_name) { |n| "Robert#{n}#{r_str}" }
p.sequence(:last_name) { |n| "Grimm#{n}#{r_str}" } p.sequence(:last_name) { |n| "Grimm#{n}#{r_str}" }
p.birthday Date.today
end end

View file

@ -0,0 +1,6 @@
source :rubygems
gem 'sinatra'
gem 'haml'
gem 'httparty'

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -0,0 +1,3 @@
require 'app'
run Sinatra::Application

View file

@ -0,0 +1,2 @@
%a{:href => '/account'}
Log in with Diaspora

View file

@ -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