social_auth 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +39 -0
- data/app/models/social_auth/facebook_service.rb +60 -0
- data/app/models/social_auth/google_plus_service.rb +106 -0
- data/app/models/social_auth/service.rb +152 -0
- data/app/models/social_auth/twitter_service.rb +67 -0
- data/config/routes.rb +2 -0
- data/lib/generators/social_auth/install/install_generator.rb +37 -0
- data/lib/generators/social_auth/install/templates/create_social_auth_services.rb +12 -0
- data/lib/generators/social_auth/install/templates/initializer.rb +15 -0
- data/lib/social_auth.rb +73 -0
- data/lib/social_auth/acts_as_social_user.rb +23 -0
- data/lib/social_auth/engine.rb +12 -0
- data/lib/social_auth/railtie.rb +7 -0
- data/lib/social_auth/version.rb +3 -0
- data/lib/tasks/social_auth_tasks.rake +4 -0
- data/spec/dummy/rails-4.2.0/Gemfile +42 -0
- data/spec/dummy/rails-4.2.0/README.rdoc +28 -0
- data/spec/dummy/rails-4.2.0/Rakefile +6 -0
- data/spec/dummy/rails-4.2.0/app/assets/javascripts/application.js +16 -0
- data/spec/dummy/rails-4.2.0/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/rails-4.2.0/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/rails-4.2.0/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/rails-4.2.0/app/models/user.rb +2 -0
- data/spec/dummy/rails-4.2.0/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/rails-4.2.0/bin/bundle +3 -0
- data/spec/dummy/rails-4.2.0/bin/rails +4 -0
- data/spec/dummy/rails-4.2.0/bin/rake +4 -0
- data/spec/dummy/rails-4.2.0/bin/setup +29 -0
- data/spec/dummy/rails-4.2.0/config.ru +4 -0
- data/spec/dummy/rails-4.2.0/config/application.rb +26 -0
- data/spec/dummy/rails-4.2.0/config/boot.rb +3 -0
- data/spec/dummy/rails-4.2.0/config/database.yml +15 -0
- data/spec/dummy/rails-4.2.0/config/environment.rb +5 -0
- data/spec/dummy/rails-4.2.0/config/environments/development.rb +41 -0
- data/spec/dummy/rails-4.2.0/config/environments/production.rb +79 -0
- data/spec/dummy/rails-4.2.0/config/environments/test.rb +42 -0
- data/spec/dummy/rails-4.2.0/config/initializers/assets.rb +11 -0
- data/spec/dummy/rails-4.2.0/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/rails-4.2.0/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/rails-4.2.0/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/rails-4.2.0/config/initializers/inflections.rb +16 -0
- data/spec/dummy/rails-4.2.0/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/rails-4.2.0/config/initializers/session_store.rb +3 -0
- data/spec/dummy/rails-4.2.0/config/initializers/social_auth.rb +15 -0
- data/spec/dummy/rails-4.2.0/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/rails-4.2.0/config/locales/en.yml +23 -0
- data/spec/dummy/rails-4.2.0/config/routes.rb +56 -0
- data/spec/dummy/rails-4.2.0/config/secrets.yml +22 -0
- data/spec/dummy/rails-4.2.0/db/migrate/20150504044515878_create_social_auth_services.rb +12 -0
- data/spec/dummy/rails-4.2.0/db/migrate/20150504044519_create_users.rb +9 -0
- data/spec/dummy/rails-4.2.0/db/schema.rb +35 -0
- data/spec/dummy/rails-4.2.0/db/seeds.rb +7 -0
- data/spec/dummy/rails-4.2.0/log/test.log +2570 -0
- data/spec/dummy/rails-4.2.0/public/404.html +67 -0
- data/spec/dummy/rails-4.2.0/public/422.html +67 -0
- data/spec/dummy/rails-4.2.0/public/500.html +66 -0
- data/spec/dummy/rails-4.2.0/public/favicon.ico +0 -0
- data/spec/dummy/rails-4.2.0/public/robots.txt +5 -0
- data/spec/dummy/rails-4.2.0/test/fixtures/users.yml +7 -0
- data/spec/dummy/rails-4.2.0/test/models/user_test.rb +7 -0
- data/spec/dummy/rails-4.2.0/test/test_helper.rb +10 -0
- data/spec/fixtures/vcr_cassettes/facebook_service/invalid_friends_request.yml +54 -0
- data/spec/fixtures/vcr_cassettes/facebook_service/invalid_request.yml +50 -0
- data/spec/fixtures/vcr_cassettes/facebook_service/invalid_token.yml +50 -0
- data/spec/fixtures/vcr_cassettes/facebook_service/valid_friends_request.yml +110 -0
- data/spec/fixtures/vcr_cassettes/facebook_service/valid_request.yml +55 -0
- data/spec/fixtures/vcr_cassettes/google_plus_service/invalid_authorization.yml +51 -0
- data/spec/fixtures/vcr_cassettes/google_plus_service/invalid_friends_request.yml +53 -0
- data/spec/fixtures/vcr_cassettes/google_plus_service/invalid_token.yml +51 -0
- data/spec/fixtures/vcr_cassettes/google_plus_service/valid_authorization.yml +56 -0
- data/spec/fixtures/vcr_cassettes/google_plus_service/valid_friends_request.yml +132 -0
- data/spec/fixtures/vcr_cassettes/google_plus_service/valid_request.yml +110 -0
- data/spec/fixtures/vcr_cassettes/twitter_service/invalid_friends_request.yml +47 -0
- data/spec/fixtures/vcr_cassettes/twitter_service/valid_friends_request.yml +159 -0
- data/spec/fixtures/vcr_cassettes/twitter_service/valid_request.yml +337 -0
- data/spec/models/facebook_service_spec.rb +127 -0
- data/spec/models/google_plus_service_spec.rb +133 -0
- data/spec/models/service_spec.rb +236 -0
- data/spec/models/twitter_service_spec.rb +100 -0
- data/spec/spec_helper.rb +74 -0
- data/spec/support/database.yml +15 -0
- data/spec/support/rails_template.rb +15 -0
- metadata +376 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7b73fa75b8a6c8200dfa7dd06516c356ed7bc6fa
|
4
|
+
data.tar.gz: 3df34c0d057b106e60658529905ad5b5d6a3258f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1806f1a18ece05d1522f280a6746b675384708be1933bc87ac940c20f2eefb129af1ae11bb4c8f98272cfb5afbd02cb3fe8bbe4ea20aa4b39fe4e1fc024cd765
|
7
|
+
data.tar.gz: 6348918e0a59e0aced64adbb948fc72ca3d86f8658e38a5fa28aa932aee3a1eedd3a1dda83b621c34958e9ef67bb77c2ee000ef21eff00ebc57b4c4572d756b9
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 William Porter
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require "bundler"
|
2
|
+
require 'rake'
|
3
|
+
Bundler.setup
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
def cmd(command)
|
7
|
+
puts command
|
8
|
+
raise unless system command
|
9
|
+
end
|
10
|
+
|
11
|
+
# Import all our rake tasks
|
12
|
+
FileList['tasks/**/*.rake'].each { |task| import task }
|
13
|
+
|
14
|
+
# begin
|
15
|
+
# require 'bundler/setup'
|
16
|
+
# rescue LoadError
|
17
|
+
# puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
18
|
+
# end
|
19
|
+
|
20
|
+
# require 'rdoc/task'
|
21
|
+
|
22
|
+
# RDoc::Task.new(:rdoc) do |rdoc|
|
23
|
+
# rdoc.rdoc_dir = 'rdoc'
|
24
|
+
# rdoc.title = 'SocialAuth'
|
25
|
+
# rdoc.options << '--line-numbers'
|
26
|
+
# rdoc.rdoc_files.include('README.rdoc')
|
27
|
+
# rdoc.rdoc_files.include('lib/**/*.rb')
|
28
|
+
# end
|
29
|
+
|
30
|
+
# APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
31
|
+
# load 'rails/tasks/engine.rake'
|
32
|
+
|
33
|
+
|
34
|
+
# load 'rails/tasks/statistics.rake'
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
# Bundler::GemHelper.install_tasks
|
39
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'fb_graph2'
|
2
|
+
|
3
|
+
module SocialAuth
|
4
|
+
class FacebookService < Service
|
5
|
+
def name
|
6
|
+
"Facebook"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.init_with(auth_token={})
|
10
|
+
request = create_connection(auth_token)
|
11
|
+
|
12
|
+
return create_with_request(
|
13
|
+
request.id,
|
14
|
+
User.create_with_facebook_request(request),
|
15
|
+
"Authenticated",
|
16
|
+
{access_token: request.access_token}
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.connect_with(user, auth_token={}, method="Connected")
|
21
|
+
request = create_connection(auth_token)
|
22
|
+
|
23
|
+
return create_with_request(
|
24
|
+
request.id,
|
25
|
+
user,
|
26
|
+
method,
|
27
|
+
{access_token: request.access_token}
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.create_connection(auth_token={})
|
32
|
+
fb_user = FbGraph2::User.me(auth_token[:access_token])
|
33
|
+
fb_user.fetch
|
34
|
+
|
35
|
+
rescue FbGraph2::Exception::InvalidToken => e
|
36
|
+
raise InvalidToken.new(e.message)
|
37
|
+
rescue FbGraph2::Exception::BadRequest => e
|
38
|
+
raise BadRequest.new(e.message)
|
39
|
+
end
|
40
|
+
|
41
|
+
def friend_ids
|
42
|
+
if redis_instance.exists(redis_key(:friends))
|
43
|
+
friend_ids = redis_instance.smembers(redis_key(:friends))
|
44
|
+
else
|
45
|
+
friend_ids = self.class.create_connection(access_token).friends.map(&:id)
|
46
|
+
unless friend_ids.empty?
|
47
|
+
redis_instance.del(redis_key(:friends))
|
48
|
+
redis_instance.sadd(redis_key(:friends), friend_ids)
|
49
|
+
redis_instance.expire(redis_key(:friends), REDIS_CACHE)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
friend_ids
|
53
|
+
|
54
|
+
rescue InvalidToken => e
|
55
|
+
disconnect(e)
|
56
|
+
return []
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'google_plus'
|
2
|
+
require 'typhoeus'
|
3
|
+
|
4
|
+
module SocialAuth
|
5
|
+
class GooglePlusService < Service
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Google Plus"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.init_with(auth_token={})
|
12
|
+
access_token = fetch_access_token(auth_token)
|
13
|
+
request = create_connection(access_token).get('me')
|
14
|
+
|
15
|
+
return create_with_request(
|
16
|
+
request.id,
|
17
|
+
User.create_with_google_plus_request(request),
|
18
|
+
"Authenticated",
|
19
|
+
{refresh_token: access_token[:refresh_token]}
|
20
|
+
)
|
21
|
+
rescue GooglePlus::RequestError => e
|
22
|
+
raise InvalidToken.new(e.message)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.connect_with(user, auth_token={}, method="Connected")
|
26
|
+
access_token = fetch_access_token(auth_token)
|
27
|
+
request = create_connection(access_token).get('me')
|
28
|
+
|
29
|
+
return create_with_request(
|
30
|
+
request.id,
|
31
|
+
user,
|
32
|
+
method,
|
33
|
+
{refresh_token: access_token[:refresh_token]}
|
34
|
+
)
|
35
|
+
rescue GooglePlus::RequestError => e
|
36
|
+
raise InvalidToken.new(e.message)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.fetch_access_token(auth_token={})
|
40
|
+
params = {
|
41
|
+
client_id: SocialAuth.google_client_id,
|
42
|
+
client_secret: SocialAuth.google_client_secret,
|
43
|
+
redirect_uri: SocialAuth.google_redirect_uri
|
44
|
+
}
|
45
|
+
if auth_token[:auth_token].present?
|
46
|
+
params[:code] = auth_token[:auth_token]
|
47
|
+
params[:grant_type] = "authorization_code"
|
48
|
+
request = Typhoeus::Request.new(
|
49
|
+
"https://www.googleapis.com/oauth2/v3/token",
|
50
|
+
method: :post,
|
51
|
+
params: params
|
52
|
+
)
|
53
|
+
else
|
54
|
+
params[:refresh_token] = auth_token[:refresh_token]
|
55
|
+
params[:grant_type] = "refresh_token"
|
56
|
+
request = Typhoeus::Request.new(
|
57
|
+
"https://www.googleapis.com/oauth2/v3/token",
|
58
|
+
method: :post,
|
59
|
+
params: params
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
request.on_complete do |response|
|
64
|
+
body = JSON.parse(response.body).with_indifferent_access
|
65
|
+
if response.success?
|
66
|
+
return body
|
67
|
+
else
|
68
|
+
raise InvalidToken.new(body[:error_description])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
request.run
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.create_connection(auth_token={})
|
76
|
+
GooglePlus.api_key = SocialAuth.google_api_key
|
77
|
+
GooglePlus.access_token = auth_token[:access_token]
|
78
|
+
GooglePlus::Person
|
79
|
+
end
|
80
|
+
|
81
|
+
def google_items
|
82
|
+
self.class.create_connection(self.class.fetch_access_token(access_token)).list.items
|
83
|
+
end
|
84
|
+
|
85
|
+
def friend_ids
|
86
|
+
if redis_instance.exists(redis_key(:friends))
|
87
|
+
friend_ids = redis_instance.smembers(redis_key(:friends))
|
88
|
+
else
|
89
|
+
items = google_items
|
90
|
+
friend_ids = items.map(&:id) if items.present?
|
91
|
+
if friend_ids.present?
|
92
|
+
redis_instance.del(redis_key(:friends))
|
93
|
+
redis_instance.sadd(redis_key(:friends), friend_ids)
|
94
|
+
redis_instance.expire(redis_key(:friends), REDIS_CACHE)
|
95
|
+
else
|
96
|
+
return []
|
97
|
+
end
|
98
|
+
end
|
99
|
+
friend_ids
|
100
|
+
|
101
|
+
rescue InvalidToken => e
|
102
|
+
disconnect
|
103
|
+
return []
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module SocialAuth
|
2
|
+
class Service < ActiveRecord::Base
|
3
|
+
#validations
|
4
|
+
validates_presence_of :user, :access_token, :remote_id, :method
|
5
|
+
validates_uniqueness_of :remote_id, scope: [:type], :if => lambda { |service| service.method == 'Authenticated' }
|
6
|
+
validates_uniqueness_of :remote_id, scope: [:type, :user_id], :if => lambda { |service| service.method == 'Connected' }
|
7
|
+
|
8
|
+
before_validation :validate_methods
|
9
|
+
|
10
|
+
#relations
|
11
|
+
belongs_to :user
|
12
|
+
|
13
|
+
#settings
|
14
|
+
self.table_name = "social_auth_services"
|
15
|
+
|
16
|
+
#callbacks
|
17
|
+
after_create :append_to_associated_services
|
18
|
+
|
19
|
+
ACCEPTED_METHODS = %w(Authenticated Connected)
|
20
|
+
REDIS_CACHE = 2_592_000 # cache expiry in seconds
|
21
|
+
|
22
|
+
def name
|
23
|
+
raise "need to implement"
|
24
|
+
end
|
25
|
+
|
26
|
+
def access_token
|
27
|
+
if super.blank?
|
28
|
+
{}
|
29
|
+
else
|
30
|
+
super.with_indifferent_access
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.init_with(auth_token)
|
35
|
+
raise "need to override"
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.connect_with(user, auth_token)
|
39
|
+
raise "need to override"
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.create_with_request(remote_id, user, method="Connected", access_token={})
|
43
|
+
remote_id = remote_id.to_s
|
44
|
+
|
45
|
+
unless (service = find_by_remote_id_and_method(remote_id, method)) && method == "Authenticated"
|
46
|
+
#attempts to look if some other user connected this same facebook account if its an authentication request
|
47
|
+
if count = where(remote_id: remote_id, method: "Connected").count == 1 and method == "Authenticated"
|
48
|
+
service = find_by_remote_id_and_method(remote_id, "Connected")
|
49
|
+
else
|
50
|
+
service = new
|
51
|
+
service.remote_id = remote_id
|
52
|
+
|
53
|
+
#gives the owner one last chance to perform some app level logic on the user before being created
|
54
|
+
user = user.validate_existing_user(remote_id, service.type) if user.respond_to?(:validate_existing_user)
|
55
|
+
service.user = user
|
56
|
+
service.method = method
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
service.access_token = access_token
|
61
|
+
service.save
|
62
|
+
|
63
|
+
return service
|
64
|
+
end
|
65
|
+
|
66
|
+
def services
|
67
|
+
self.class.where('remote_id IN (?)', friend_ids)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.append_to_associated_services(id)
|
71
|
+
service = find(id)
|
72
|
+
service.services.each do |s|
|
73
|
+
s.append_to_friends_list(service)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def append_to_friends_list(service)
|
78
|
+
if redis_instance.exists(self.redis_key(:friends))
|
79
|
+
redis_instance.sadd(self.redis_key(:friends), service.remote_id)
|
80
|
+
end
|
81
|
+
user.friend_joined_the_app_callback(service.user) if user.respond_to?(:friend_joined_the_app_callback)
|
82
|
+
end
|
83
|
+
|
84
|
+
def friend_ids
|
85
|
+
if redis_instance.exists(redis_key(:friends))
|
86
|
+
friend_ids = redis_instance.smembers(redis_key(:friends))
|
87
|
+
else
|
88
|
+
[]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.disconnect_user(user)
|
93
|
+
service = find_by_user_id(user.id)
|
94
|
+
if service
|
95
|
+
raise Error.new("Cannot disconnect a service you used to authenticate with") if service.authenticated?
|
96
|
+
|
97
|
+
service.disconnect(nil, false)
|
98
|
+
else
|
99
|
+
raise ServiceDoesNotExist.new("Couldn't find service for this user")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def disconnect(e=nil, callback=true)
|
104
|
+
if connected?
|
105
|
+
#destroys service
|
106
|
+
self.destroy
|
107
|
+
#notifies the user that their service is about to be disconnected
|
108
|
+
user.service_disconnected_callback(self) if user.respond_to?(:service_disconnected_callback) and callback
|
109
|
+
else
|
110
|
+
#re_raises the exception
|
111
|
+
raise InvalidToken.new(e ? e.message : "Token has become invalid") #move to localization file
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# helper method to generate redis keys
|
116
|
+
def redis_key(str)
|
117
|
+
"#{type}:#{id}:#{str}"
|
118
|
+
end
|
119
|
+
|
120
|
+
def redis_instance
|
121
|
+
$redis #need to change out for an configurable var
|
122
|
+
end
|
123
|
+
|
124
|
+
def authenticated?
|
125
|
+
return true if method == 'Authenticated'
|
126
|
+
false
|
127
|
+
end
|
128
|
+
|
129
|
+
def connected?
|
130
|
+
return true if method == 'Connected'
|
131
|
+
false
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def validate_methods
|
137
|
+
errors.add(:method, 'not an accepted option') unless ACCEPTED_METHODS.include?(method)
|
138
|
+
end
|
139
|
+
|
140
|
+
def append_to_associated_services
|
141
|
+
self.class.delay.append_to_associated_services(self.id)
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
#exceptions
|
147
|
+
class InvalidToken < StandardError ; end
|
148
|
+
class BadRequest < StandardError ; end
|
149
|
+
class ServiceDoesNotExist < StandardError ; end
|
150
|
+
class Error < StandardError ; end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'twitter'
|
2
|
+
|
3
|
+
module SocialAuth
|
4
|
+
class TwitterService < Service
|
5
|
+
|
6
|
+
def name
|
7
|
+
"Twitter"
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.init_with(auth_token={})
|
11
|
+
request = create_connection(auth_token)
|
12
|
+
|
13
|
+
return create_with_request(
|
14
|
+
request.user.id,
|
15
|
+
User.create_with_twitter_request(request.user),
|
16
|
+
"Authenticated",
|
17
|
+
{access_token: request.access_token, access_token_secret: request.access_token_secret}
|
18
|
+
)
|
19
|
+
|
20
|
+
rescue Twitter::Error::Unauthorized => e
|
21
|
+
raise InvalidToken.new(e.message)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.connect_with(user, auth_token={}, method="Connected")
|
25
|
+
request = create_connection(auth_token)
|
26
|
+
|
27
|
+
return create_with_request(
|
28
|
+
request.user.id,
|
29
|
+
user,
|
30
|
+
method,
|
31
|
+
{access_token: request.access_token, access_token_secret: request.access_token_secret}
|
32
|
+
)
|
33
|
+
|
34
|
+
rescue Twitter::Error::Unauthorized => e
|
35
|
+
raise InvalidToken.new(e.message)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.create_connection(auth_token={})
|
39
|
+
Twitter::REST::Client.new do |config|
|
40
|
+
config.consumer_key = SocialAuth.twitter_consumer_key
|
41
|
+
config.consumer_secret = SocialAuth.twitter_consumer_secret
|
42
|
+
config.access_token = auth_token[:access_token]
|
43
|
+
config.access_token_secret = auth_token[:access_token_secret]
|
44
|
+
end
|
45
|
+
#the reason why we don't catch any exceptions here is because it only initializes the connection no
|
46
|
+
#requests are actually made here
|
47
|
+
end
|
48
|
+
|
49
|
+
def friend_ids
|
50
|
+
if redis_instance.exists(redis_key(:friends))
|
51
|
+
friend_ids = redis_instance.smembers(redis_key(:friends))
|
52
|
+
else
|
53
|
+
friend_ids = self.class.create_connection(access_token).friend_ids.to_hash[:ids].map(&:to_s)
|
54
|
+
unless friend_ids.empty?
|
55
|
+
redis_instance.del(redis_key(:friends))
|
56
|
+
redis_instance.sadd(redis_key(:friends), friend_ids.to_s)
|
57
|
+
redis_instance.expire(redis_key(:friends), REDIS_CACHE)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
friend_ids
|
61
|
+
rescue Twitter::Error::Unauthorized => e
|
62
|
+
disconnect
|
63
|
+
return []
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|