cornflakeomnisocial 0.1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # OmniSocial
2
+
3
+ A Rails 3 engine for Twitter and Facebook logins using [OmniAuth](http://github.com/intridea/omniauth)
4
+
5
+ ## Installation
6
+
7
+ To use OmniSocial in a Rails 3 application:
8
+
9
+ 1. Require it in the Gemfile: `gem 'omnisocial'`
10
+
11
+ 2. Install it by running `bundle`.
12
+
13
+ 3. Run `rails g omnisocial` to copy an initializer and some CSS and image assets into your base application directory.
14
+
15
+ 4. Edit `config/initializers/omnisocial.rb` and include your application's Twitter and Facebook OAuth configuration.
16
+
17
+ 5. Run `rake db:migrate` to create the user and login_account tables.
18
+
19
+ 6. Test that the logins work by accessing `/login` inside your application.
20
+
21
+ Some more detailed installation instructions are in the [project announcement article](http://icelab.com.au/articles/welcome-to-the-omnisocial/).
22
+
23
+ ## Copyright & License
24
+
25
+ OmniSocial is Copyright (c) 2010 [Tim Riley](http://openmonkey.com/) and [Icelab](http://icelab.com.au/), and is released under MIT License.
26
+
27
+ The "Sign in with Twitter/Facebook" buttons are from [Komodo Media](http://www.komodomedia.com/blog/2009/05/sign-in-with-twitter-and-facebook-buttons/), distributeed under the [Creative Commons Attribution-Share Alike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/).
28
+
29
+ The twitter bird image is courtesy of [Pasquale D’Silva](http://wefunction.com/2008/07/freebie-twitter-icons-illustration/).
30
+
@@ -0,0 +1,55 @@
1
+ module Omnisocial
2
+ class AuthController < ApplicationController
3
+
4
+ unloadable
5
+
6
+ def new
7
+ if current_user?
8
+ flash[:notice] = 'You are already signed in. Please sign out if you want to sign in as a different user.'
9
+ redirect_to(root_path)
10
+ end
11
+ end
12
+
13
+ def callback
14
+ @account = case request.env['rack.auth']['provider']
15
+ when 'twitter' then
16
+ Omnisocial::TwitterAccount.find_or_create_from_auth_hash(request.env['rack.auth'])
17
+ when 'facebook' then
18
+ Omnisocial::FacebookAccount.find_or_create_from_auth_hash(request.env['rack.auth'])
19
+ end
20
+ if current_user && @account.user != current_user
21
+ @account.update_attributes(:user => current_user)
22
+ end
23
+ if @account.user
24
+ self.current_user = @account.user
25
+ flash[:message] = 'You have logged in successfully.'
26
+ redirect_back_or_default(root_path)
27
+ else
28
+ @user = ::User.new(:display_name => @account.name)
29
+ end
30
+ end
31
+
32
+ def confirm
33
+ @account = Omnisocial::LoginAccount.find(params[:account_id])
34
+ @user = ::User.new(params[:user].merge(:picture_url => @account.picture_url))
35
+ if @user.save
36
+ @account.update_attributes(:user => @user)
37
+ self.current_user = @user
38
+ flash[:message] = 'You have logged in successfully.'
39
+ redirect_back_or_default(root_path)
40
+ else
41
+ render :action => "callback"
42
+ end
43
+ end
44
+
45
+ def failure
46
+ flash[:error] = "We had trouble signing you in. Did you make sure to grant access? Please select a service below and try again."
47
+ render :action => 'new'
48
+ end
49
+
50
+ def destroy
51
+ logout!
52
+ redirect_to(session['return_to'] || root_path)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,23 @@
1
+ module Omnisocial
2
+ module AuthHelper
3
+ def auth_request_path(options = {})
4
+ "/auth/#{options[:service]}"
5
+ end
6
+
7
+ def big_twitter_login_button
8
+ content_tag(:a, content_tag(:span, 'Sign in with Twitter'), :class => 'omnisocial-button twitter', :href => auth_request_path(:service => 'twitter'))
9
+ end
10
+
11
+ def big_facebook_login_button
12
+ content_tag(:a, content_tag(:span, 'Sign in with Facebook'), :class => 'omnisocial-button facebook', :href => auth_request_path(:service => 'facebook'))
13
+ end
14
+
15
+ def twitter_login_button
16
+ content_tag(:a, content_tag(:img, :src => '/images/omnisocial/signin_twitter.png', :alt => 'Sign in with Twitter'), :href => auth_request_path(:service => 'twitter'))
17
+ end
18
+
19
+ def facebook_login_button
20
+ content_tag(:a, content_tag(:img, :src => '/images/omnisocial/signin_facebook.png', :alt => 'Sign in with Facebook'), :href => auth_request_path(:service => 'facebook'))
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module Omnisocial
2
+ class FacebookAccount < LoginAccount
3
+ def assign_account_info(auth_hash)
4
+ self.token = auth_hash['credentials']['token']
5
+ self.remote_account_id = auth_hash['uid']
6
+ self.login = auth_hash['user_info']['nickname']
7
+ self.name = auth_hash['user_info']['name']
8
+ self.picture_url = generate_picture_url
9
+ end
10
+
11
+ def account_url
12
+ "http://facebook.com/#{self.login}"
13
+ end
14
+
15
+ def generate_picture_url
16
+ if self.login.include?('profile.php')
17
+ "https://graph.facebook.com/#{self.login.gsub(/[^\d]/, '')}/picture?type=square"
18
+ else
19
+ "https://graph.facebook.com/#{self.login}/picture?type=square"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ module Omnisocial
2
+ class LoginAccount
3
+ include Mongoid::Document
4
+ include Mongoid::Timestamps
5
+
6
+ referenced_in :user
7
+
8
+ field :token
9
+ field :secret
10
+ field :remote_account_id
11
+ field :name
12
+ field :login
13
+ field :picture_url
14
+
15
+ def self.find_or_create_from_auth_hash(auth_hash)
16
+ if (account = first(:conditions => {:remote_account_id => auth_hash['uid']}))
17
+ account.assign_account_info(auth_hash)
18
+ account.save
19
+ account
20
+ else
21
+ create_from_auth_hash(auth_hash)
22
+ end
23
+ end
24
+
25
+ def self.create_from_auth_hash(auth_hash)
26
+ account = create!
27
+ account.assign_account_info(auth_hash)
28
+ account.save
29
+ account
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,16 @@
1
+ module Omnisocial
2
+ class TwitterAccount < LoginAccount
3
+ def assign_account_info(auth_hash)
4
+ self.token = auth_hash['credentials']['token']
5
+ self.secret = auth_hash['credentials']['secret']
6
+ self.remote_account_id = auth_hash['uid']
7
+ self.login = auth_hash['user_info']['nickname']
8
+ self.picture_url = auth_hash['user_info']['image']
9
+ self.name = auth_hash['user_info']['name']
10
+ end
11
+
12
+ def account_url
13
+ "http://twitter.com/#{self.login}"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Omnisocial
2
+ class User
3
+ include Mongoid::Document
4
+ include Mongoid::Timestamps
5
+
6
+ field :remember_token
7
+ field :display_name
8
+ field :email_address
9
+ field :picture_url
10
+
11
+ references_many :login_accounts, :class_name => 'Omnisocial::LoginAccount', :dependent => :destroy
12
+
13
+ validates_presence_of :display_name, :email_address
14
+
15
+ def facebook_account
16
+ login_accounts.select{|account| account.kind_of? FacebookAccount}.first
17
+ end
18
+
19
+ def from_facebook?
20
+ !!facebook_account
21
+ end
22
+
23
+ def from_twitter?
24
+ !!twitter_account
25
+ end
26
+
27
+ def twitter_account
28
+ login_accounts.select{|account| account.kind_of? TwitterAccount}.first
29
+ end
30
+
31
+ def remember
32
+ update_attributes(:remember_token => ::BCrypt::Password.create("#{Time.now}-#{self.login_accounts.first.type}-#{self.login_accounts.first.login}")) unless new_record?
33
+ end
34
+
35
+ def forget
36
+ update_attributes(:remember_token => nil) unless new_record?
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ <%= form_for @user, :url => confirm_path(:account_id => @account) do |f| %>
2
+ <%= f.error_messages %>
3
+
4
+ <%= f.label :display_name %>:
5
+ <%= f.text_field :display_name %><br />
6
+
7
+ <%= f.label :email_address %>:
8
+ <%= f.text_field :email_address %><br />
9
+
10
+ <%= f.submit %>
11
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <div id="omnisocial-login">
2
+ <% if flash[:error] -%>
3
+ <div class="error">
4
+ <p>
5
+ <%= flash[:error] %>
6
+ </p>
7
+ </div>
8
+ <% end -%>
9
+ <div class="information">
10
+ <h1>Sign in (or up)</h1>
11
+ <p class="large">
12
+ You can use either your Twitter or Facebook account to sign in or sign up.
13
+ </p>
14
+ <p>
15
+ Select your preferred method and you'll be sent off to authorise us to use your account.
16
+ </p>
17
+ <p>
18
+ It&#8217;ll only take a second and your information will be perfectly safe. We don't get access to your password and <em>we won't post or tweet anything from your account</em> without your explicit permission.
19
+ </p>
20
+ </div>
21
+ <%= big_twitter_login_button %>
22
+ <%= big_facebook_login_button %>
23
+ </div>
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ Rails::Application.routes.draw do
2
+ match '/login' => 'omnisocial/auth#new', :as => :login
3
+ match '/auth/:service/callback' => 'omnisocial/auth#callback'
4
+ match '/auth/confirm/:account_id' => 'omnisocial/auth#confirm', :as => :confirm
5
+ match '/auth/failure' => 'omnisocial/auth#failure'
6
+ match '/logout' => 'omnisocial/auth#destroy', :as => :logout
7
+ end
@@ -0,0 +1,62 @@
1
+ class ActionController::Base
2
+ def self.require_user(options = {})
3
+ raise Exception, "require_user cannot be called on ActionController::Base. Only it's subclasses" if self == ActionController::Base
4
+ prepend_before_filter :require_user, options
5
+ end
6
+
7
+ helper_method :current_user, :current_user?
8
+
9
+ protected
10
+
11
+ # Filters
12
+
13
+ def require_user
14
+ current_user.present? || deny_access
15
+ end
16
+
17
+ # Utils
18
+
19
+ def store_location
20
+ session[:return_to] = request.fullpath
21
+ end
22
+
23
+ def deny_access(url = nil)
24
+ store_location
25
+ redirect_to url || login_path
26
+ end
27
+
28
+ def redirect_back_or_default(default)
29
+ redirect_to(session[:return_to] || default)
30
+ session[:return_to] = nil
31
+ end
32
+
33
+ def current_user
34
+ @current_user ||= if session[:user_id]
35
+ User.first(:conditions => {:id => session[:user_id]})
36
+ elsif cookies[:remember_token]
37
+ User.first(:conditions => {:remember_token => cookies[:remember_token]})
38
+ else
39
+ false
40
+ end
41
+ end
42
+
43
+ def current_user?
44
+ !!current_user
45
+ end
46
+
47
+ def current_user=(user)
48
+ user.tap do |user|
49
+ user.remember
50
+ session[:user_id] = user.id
51
+ cookies[:remember_token] = user.remember_token
52
+ end
53
+ end
54
+
55
+ def logout!
56
+ session[:user_id] = nil
57
+ @current_user = nil
58
+ cookies.delete(:remember_token)
59
+ session[:return_to] = nil
60
+ end
61
+
62
+ end
@@ -0,0 +1,35 @@
1
+ require 'rails/generators'
2
+
3
+ module Omnisocial
4
+ module Generators
5
+ class OmnisocialGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ desc 'Creates an omnisocial initializer and copies image and CSS assets.'
9
+
10
+ def self.source_root
11
+ File.join(File.dirname(__FILE__), 'templates')
12
+ end
13
+
14
+ def copy_initializer
15
+ template 'omnisocial.rb', 'config/initializers/omnisocial.rb'
16
+ end
17
+
18
+ def copy_user_model
19
+ template 'user.rb', 'app/models/user.rb'
20
+ end
21
+
22
+ def copy_assets
23
+ copy_file 'assets/stylesheets/omnisocial.css', 'public/stylesheets/omnisocial.css'
24
+ copy_file 'assets/images/twitter.gif', 'public/images/omnisocial/twitter.gif'
25
+ copy_file 'assets/images/facebook.png', 'public/images/omnisocial/facebook.png'
26
+ copy_file 'assets/images/signin_twitter.png', 'public/images/omnisocial/signin_twitter.png'
27
+ copy_file 'assets/images/signin_facebook.png', 'public/images/omnisocial/signin_facebook.png'
28
+ end
29
+
30
+ def show_readme
31
+ readme 'README' if behavior == :invoke
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,6 @@
1
+
2
+ ===============================================================================
3
+
4
+ Welcome to the OmniSocial.
5
+
6
+ ===============================================================================
@@ -0,0 +1,68 @@
1
+ #omnisocial-login {
2
+ overflow: hidden;
3
+ }
4
+
5
+ #omnisocial-login .information {
6
+ float: left;
7
+ margin-right: 40px;
8
+ width: 450px;
9
+ }
10
+
11
+ a.omnisocial-button {
12
+ text-decoration: none;
13
+ }
14
+ a.omnisocial-button span {
15
+ -webkit-border-radius: 3px;
16
+ -moz-border-radius: 3px;
17
+ border-width: 1px;
18
+ border-style: solid;
19
+ font-weight: bold;
20
+ font-family: "proxima-nova-condensed-1", "proxima-nova-condensed-2", Helvetica, Arial, Verdana, sans-serif;
21
+ font-size: 16px;
22
+ cursor: pointer;
23
+ display: inline-block;
24
+ line-height: 1;
25
+ margin-top: 1px;
26
+ padding: 8px 10px 9px;
27
+ position: relative;
28
+ text-decoration: none;
29
+ text-shadow: rgba(0, 0, 0, 0.4) 0 -1px 0px;
30
+ background: #3583cf;
31
+ background: -webkit-gradient(linear, left top, left bottom, from(#629ed9), to(#3583cf));
32
+ border-color: #bbe2f8;
33
+ color: white;
34
+ float: none;
35
+ font-size: 18px;
36
+ position: absolute;
37
+ }
38
+ a:hover.omnisocial-button span {
39
+ text-shadow: rgba(0, 0, 0, 0.4) 0 -1px 0px;
40
+ background: #6ca520;
41
+ background: -webkit-gradient(linear, left top, left bottom, from(#90bb58), to(#6ca520));
42
+ border-color: #dcf1bf;
43
+ -o-box-shadow: rgba(0, 0, 0, 0.5) 0 0 5px 0;
44
+ -webkit-box-shadow: rgba(0, 0, 0, 0.5) 0 0 5px 0;
45
+ -moz-box-shadow: rgba(0, 0, 0, 0.5) 0 0 5px 0;
46
+ box-shadow: rgba(0, 0, 0, 0.5) 0 0 5px 0;
47
+ }
48
+
49
+ a.omnisocial-button.twitter {
50
+ background: url(/images/omnisocial/twitter.gif) center center no-repeat;
51
+ float: left;
52
+ height: 255px;
53
+ width: 200px;
54
+ }
55
+ a.omnisocial-button.twitter span {
56
+ margin: 240px 0 0 25px;
57
+ }
58
+
59
+ a.omnisocial-button.facebook {
60
+ background: url(/images/omnisocial/facebook.png) center center no-repeat;
61
+ float: left;
62
+ margin-left: 40px;
63
+ height: 255px;
64
+ width: 200px;
65
+ }
66
+ a.omnisocial-button.facebook span {
67
+ margin: 240px 0 0 11px;
68
+ }
@@ -0,0 +1,19 @@
1
+ Omnisocial.setup do |config|
2
+
3
+ # ==> Twitter
4
+ # config.twitter 'APP_KEY', 'APP_SECRET'
5
+
6
+ # ==> Facebook
7
+ # config.facebook 'APP_KEY', 'APP_SECRET', :scope => 'publish_stream'
8
+
9
+ if Rails.env.production?
10
+
11
+ # Configs for production mode go here
12
+
13
+ elsif Rails.env.development?
14
+
15
+ # Configs for development mode go here
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,3 @@
1
+ class User < Omnisocial::User
2
+ # Make any customisations here
3
+ end
data/lib/omnisocial.rb ADDED
@@ -0,0 +1,24 @@
1
+ module Omnisocial
2
+ require 'omnisocial/service_config'
3
+
4
+ # Twitter & Facebook app configs
5
+ mattr_accessor :service_configs
6
+ @@service_configs = {}
7
+
8
+ def self.setup
9
+ yield self
10
+ end
11
+
12
+ # config.twitter APP_KEY, APP_SECRET, :scope => ['foo', 'bar']
13
+ def self.twitter(app_key, app_secret, options = {})
14
+ @@service_configs[:twitter] = Omnisocial::ServiceConfig.new(app_key, app_secret, options)
15
+ end
16
+
17
+ def self.facebook(app_key, app_secret, options = {})
18
+ @@service_configs[:facebook] = Omnisocial::ServiceConfig.new(app_key, app_secret, options)
19
+ end
20
+
21
+ require 'omnisocial/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
22
+ end
23
+
24
+ require 'extensions/action_controller/base'
@@ -0,0 +1,33 @@
1
+ require 'omnisocial'
2
+
3
+ require 'rails'
4
+ require 'action_controller'
5
+
6
+ require 'omniauth/core'
7
+ require 'omniauth/oauth'
8
+ require 'bcrypt'
9
+
10
+ module Omnisocial
11
+ class Engine < Rails::Engine
12
+
13
+ config.to_prepare do
14
+ ApplicationController.helper(Omnisocial::AuthHelper)
15
+ end
16
+
17
+ initializer 'omnisocial.load_middleware', :after=> :load_config_initializers do
18
+ if Omnisocial.service_configs[:twitter]
19
+ config.app_middleware.use ::OmniAuth::Strategies::Twitter,
20
+ Omnisocial.service_configs[:twitter].app_key,
21
+ Omnisocial.service_configs[:twitter].app_secret
22
+ end
23
+
24
+ if Omnisocial.service_configs[:facebook]
25
+ config.app_middleware.use ::OmniAuth::Strategies::Facebook,
26
+ Omnisocial.service_configs[:facebook].app_key,
27
+ Omnisocial.service_configs[:facebook].app_secret,
28
+ Omnisocial.service_configs[:facebook].options
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ require 'ostruct'
2
+
3
+ module Omnisocial
4
+ class ServiceConfig < OpenStruct
5
+ def initialize(app_key, app_secret, options)
6
+ super(
7
+ :app_key => app_key,
8
+ :app_secret => app_secret,
9
+ :options => options
10
+ )
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Omnisocial
2
+ VERSION = '0.1.2.3'.freeze
3
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cornflakeomnisocial
3
+ version: !ruby/object:Gem::Version
4
+ hash: 73
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 2
10
+ - 3
11
+ version: 0.1.2.3
12
+ platform: ruby
13
+ authors:
14
+ - Jason Kotchoff
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-01-10 00:00:00 +11:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 31
29
+ segments:
30
+ - 0
31
+ - 1
32
+ - 2
33
+ version: 0.1.2
34
+ prerelease: false
35
+ type: :runtime
36
+ name: oa-core
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 31
45
+ segments:
46
+ - 0
47
+ - 1
48
+ - 2
49
+ version: 0.1.2
50
+ prerelease: false
51
+ type: :runtime
52
+ name: oa-oauth
53
+ version_requirements: *id002
54
+ - !ruby/object:Gem::Dependency
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 1
61
+ segments:
62
+ - 2
63
+ - 1
64
+ version: "2.1"
65
+ prerelease: false
66
+ type: :runtime
67
+ name: bcrypt-ruby
68
+ version_requirements: *id003
69
+ description: Twitter and Facebook logins for your Rails application.
70
+ email: jason@projectproject.com.au
71
+ executables: []
72
+
73
+ extensions: []
74
+
75
+ extra_rdoc_files: []
76
+
77
+ files:
78
+ - README.md
79
+ - lib/generators/omnisocial/templates/omnisocial.rb
80
+ - lib/generators/omnisocial/templates/assets/images/signin_twitter.png
81
+ - lib/generators/omnisocial/templates/assets/images/twitter.gif
82
+ - lib/generators/omnisocial/templates/assets/images/signin_facebook.png
83
+ - lib/generators/omnisocial/templates/assets/images/facebook.png
84
+ - lib/generators/omnisocial/templates/assets/stylesheets/omnisocial.css
85
+ - lib/generators/omnisocial/templates/README
86
+ - lib/generators/omnisocial/templates/user.rb
87
+ - lib/generators/omnisocial/omnisocial_generator.rb
88
+ - lib/omnisocial/service_config.rb
89
+ - lib/omnisocial/version.rb
90
+ - lib/omnisocial/engine.rb
91
+ - lib/omnisocial.rb
92
+ - lib/extensions/action_controller/base.rb
93
+ - app/models/omnisocial/login_account.rb
94
+ - app/models/omnisocial/twitter_account.rb
95
+ - app/models/omnisocial/facebook_account.rb
96
+ - app/models/omnisocial/user.rb
97
+ - app/helpers/omnisocial/auth_helper.rb
98
+ - app/views/omnisocial/auth/new.html.erb
99
+ - app/views/omnisocial/auth/callback.html.erb
100
+ - app/controllers/omnisocial/auth_controller.rb
101
+ - config/routes.rb
102
+ has_rdoc: true
103
+ homepage: http://github.com/icelab/omnisocial
104
+ licenses: []
105
+
106
+ post_install_message:
107
+ rdoc_options: []
108
+
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ hash: 3
117
+ segments:
118
+ - 0
119
+ version: "0"
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ hash: 3
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ requirements: []
130
+
131
+ rubyforge_project:
132
+ rubygems_version: 1.3.7
133
+ signing_key:
134
+ specification_version: 3
135
+ summary: Twitter and Facebook logins for your Rails application.
136
+ test_files: []
137
+