Add Chubbies, the oauth sample app, and a cucumber feature for part of an oauth flow
This commit is contained in:
parent
8841f62cf0
commit
381b85189d
24 changed files with 356 additions and 404 deletions
6
Gemfile
6
Gemfile
|
|
@ -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
|
||||||
|
|
|
||||||
10
Gemfile.lock
10
Gemfile.lock
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
18
app/controllers/authorizations_controller.rb
Normal file
18
app/controllers/authorizations_controller.rb
Normal 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
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
7
app/views/authorizations/new.html.haml
Normal file
7
app/views/authorizations/new.html.haml
Normal 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"
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
42
db/migrate/20110526184644_add_oauth2_tables.rb
Normal file
42
db/migrate/20110526184644_add_oauth2_tables.rb
Normal 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
|
||||||
32
db/schema.rb
32
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_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
29
features/oauth.feature
Normal 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?"
|
||||||
|
|
||||||
70
features/step_definitions/oauth_steps.rb
Normal file
70
features/step_definitions/oauth_steps.rb
Normal 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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
6
spec/support/chubbies/Gemfile
Normal file
6
spec/support/chubbies/Gemfile
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
source :rubygems
|
||||||
|
|
||||||
|
gem 'sinatra'
|
||||||
|
gem 'haml'
|
||||||
|
|
||||||
|
gem 'httparty'
|
||||||
20
spec/support/chubbies/Gemfile.lock
Normal file
20
spec/support/chubbies/Gemfile.lock
Normal 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
|
||||||
8
spec/support/chubbies/README
Normal file
8
spec/support/chubbies/README
Normal 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.
|
||||||
75
spec/support/chubbies/app.rb
Normal file
75
spec/support/chubbies/app.rb
Normal 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
|
||||||
3
spec/support/chubbies/config.ru
Normal file
3
spec/support/chubbies/config.ru
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
require 'app'
|
||||||
|
|
||||||
|
run Sinatra::Application
|
||||||
2
spec/support/chubbies/views/home.haml
Normal file
2
spec/support/chubbies/views/home.haml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
%a{:href => '/account'}
|
||||||
|
Log in with Diaspora
|
||||||
13
spec/support/chubbies/views/response.haml
Normal file
13
spec/support/chubbies/views/response.haml
Normal 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
|
||||||
|
|
||||||
Loading…
Reference in a new issue