motion-firebase 2.1.5 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +192 -64
- data/lib/firebase-auth/firebase_simple_login.rb +0 -76
- data/lib/firebase/fdata_snapshot.rb +4 -0
- data/lib/firebase/firebase.rb +53 -42
- data/lib/firebase/firebase_auth.rb +219 -0
- data/lib/firebase/firebase_facebook_helper.rb +24 -0
- data/lib/firebase/firebase_github_helper.rb +20 -0
- data/lib/firebase/firebase_twitter_helper.rb +169 -0
- data/lib/firebase/fquery.rb +16 -4
- data/lib/firebase/version.rb +2 -1
- data/lib/motion-firebase-auth.rb +3 -11
- data/lib/motion-firebase.rb +3 -1
- metadata +6 -19
- data/lib/vendor/Firebase.framework/Firebase +0 -0
- data/lib/vendor/Firebase.framework/Versions/A/Firebase +0 -0
- data/lib/vendor/Firebase.framework/Versions/A/Headers/FDataSnapshot.h +0 -146
- data/lib/vendor/Firebase.framework/Versions/A/Headers/FEventType.h +0 -43
- data/lib/vendor/Firebase.framework/Versions/A/Headers/FMutableData.h +0 -139
- data/lib/vendor/Firebase.framework/Versions/A/Headers/FQuery.h +0 -229
- data/lib/vendor/Firebase.framework/Versions/A/Headers/FTransactionResult.h +0 -50
- data/lib/vendor/Firebase.framework/Versions/A/Headers/Firebase.h +0 -707
- data/lib/vendor/Firebase.framework/build-MacOSX/Firebase.framework.bridgesupport +0 -582
- data/lib/vendor/Firebase.framework/build-iPhoneSimulator/Firebase.framework.bridgesupport +0 -582
- data/lib/vendor/FirebaseSimpleLogin.framework/FirebaseSimpleLogin +0 -0
- data/lib/vendor/FirebaseSimpleLogin.framework/Versions/A/FirebaseSimpleLogin +0 -0
- data/lib/vendor/FirebaseSimpleLogin.framework/Versions/A/Headers/FATypes.h +0 -52
- data/lib/vendor/FirebaseSimpleLogin.framework/Versions/A/Headers/FAUser.h +0 -97
- data/lib/vendor/FirebaseSimpleLogin.framework/Versions/A/Headers/FirebaseSimpleLogin.h +0 -221
- data/lib/vendor/FirebaseSimpleLogin.framework/build-MacOSX/FirebaseSimpleLogin.framework.bridgesupport +0 -230
- data/lib/vendor/FirebaseSimpleLogin.framework/build-iPhoneSimulator/FirebaseSimpleLogin.framework.bridgesupport +0 -230
data/lib/firebase/firebase.rb
CHANGED
@@ -22,8 +22,41 @@ class Firebase
|
|
22
22
|
return event_type
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.
|
26
|
-
|
25
|
+
def self.url=(url)
|
26
|
+
if url.start_with?('http://')
|
27
|
+
raise "Invalid URL #{url.inspect} in #{__method__}: URL scheme should be 'https://', not 'http://'"
|
28
|
+
elsif url.start_with?('https://')
|
29
|
+
# all good
|
30
|
+
elsif url =~ '^\w+://'
|
31
|
+
raise "Invalid URL #{url.inspect} in #{__method__}: URL scheme should be 'https://', not '#{$~}'"
|
32
|
+
else
|
33
|
+
url = "https://#{url}"
|
34
|
+
end
|
35
|
+
|
36
|
+
# should we support `Firebase.url = 'myapp/path/to/child/'` ? I'm gonna say
|
37
|
+
# NO for now...
|
38
|
+
unless url.include?('.firebaseio.com')
|
39
|
+
if url.include?('/')
|
40
|
+
raise "Invalid URL #{url.inspect} in #{__method__}: URL does not include 'firebaseio.com'"
|
41
|
+
end
|
42
|
+
url = "#{url}.firebaseio.com"
|
43
|
+
end
|
44
|
+
|
45
|
+
@url = url
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.url
|
49
|
+
@url
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.new(url=nil)
|
53
|
+
if url.nil?
|
54
|
+
@shared ||= alloc.initWithUrl(@url)
|
55
|
+
elsif url
|
56
|
+
alloc.initWithUrl(url)
|
57
|
+
else
|
58
|
+
super
|
59
|
+
end
|
27
60
|
end
|
28
61
|
|
29
62
|
# @example
|
@@ -36,52 +69,35 @@ class Firebase
|
|
36
69
|
setDispatchQueue(queue)
|
37
70
|
end
|
38
71
|
|
39
|
-
|
40
|
-
|
41
|
-
# firebase.auth('secretkey') do
|
42
|
-
# # connected
|
43
|
-
# end
|
44
|
-
# firebase.auth('secretkey', disconnect: ->{}) do
|
45
|
-
# # connected
|
46
|
-
# end
|
47
|
-
# firebase.auth('secretkey', completion: ->{}, disconnect: ->{})
|
48
|
-
# # => firebase.authWithCredential(credential)
|
49
|
-
def auth(credential, options={}, &and_then)
|
50
|
-
and_then ||= options[:completion]
|
51
|
-
disconnect_block = options[:disconnect]
|
52
|
-
authWithCredential(credential, withCompletionBlock: and_then, withCancelBlock: disconnect_block)
|
53
|
-
return self
|
72
|
+
def connected_state(&block)
|
73
|
+
connected?
|
54
74
|
end
|
55
75
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
76
|
+
def self.connected?(&block)
|
77
|
+
Firebase.new.connected?(&block)
|
78
|
+
end
|
79
|
+
def connected?(&block)
|
80
|
+
if block
|
81
|
+
connected_state.on(:value) do |snapshot|
|
82
|
+
block.call(snapshot.value?)
|
83
|
+
end
|
61
84
|
else
|
62
|
-
|
85
|
+
self.root['.info/connected']
|
63
86
|
end
|
64
87
|
end
|
65
88
|
|
66
|
-
def
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
def connected_state
|
71
|
-
self.root['.info/connected']
|
89
|
+
def self.offline!
|
90
|
+
Firebase.new.offline!
|
72
91
|
end
|
73
|
-
|
74
92
|
def offline!
|
75
|
-
goOffline
|
93
|
+
self.goOffline
|
76
94
|
end
|
77
95
|
|
78
|
-
def online!
|
79
|
-
|
96
|
+
def self.online!
|
97
|
+
Firebase.new.online!
|
80
98
|
end
|
81
|
-
|
82
|
-
|
83
|
-
NSLog('The method ‘Firebase#run’ has been deprecated in favor of ‘Firebase#transaction’')
|
84
|
-
self.transaction(options, &transaction)
|
99
|
+
def online!
|
100
|
+
self.goOnline
|
85
101
|
end
|
86
102
|
|
87
103
|
def transaction(options={}, &transaction)
|
@@ -201,11 +217,6 @@ class Firebase
|
|
201
217
|
return self
|
202
218
|
end
|
203
219
|
|
204
|
-
# Calls the block when the value is true
|
205
|
-
def on_auth(options={}, &block)
|
206
|
-
auth_state.on(:value, options, &block)
|
207
|
-
end
|
208
|
-
|
209
220
|
def on_disconnect(value, &and_then)
|
210
221
|
if block_given?
|
211
222
|
if value.nil?
|
@@ -0,0 +1,219 @@
|
|
1
|
+
# most methods have a static version that make use of Firebase.url = 'global url'
|
2
|
+
# to create a Firebase ref.
|
3
|
+
class Firebase
|
4
|
+
|
5
|
+
def self.auth_data
|
6
|
+
Firebase.new.auth_data
|
7
|
+
end
|
8
|
+
def auth_data
|
9
|
+
authData
|
10
|
+
end
|
11
|
+
|
12
|
+
# @example
|
13
|
+
# Firebase.auth('secrettoken') do |error, auth_data|
|
14
|
+
# if auth_data
|
15
|
+
# # authenticated
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
def self.auth(token, options={}, &block)
|
19
|
+
Firebase.new.auth(token, options, &block)
|
20
|
+
end
|
21
|
+
def auth(token, options={}, &and_then)
|
22
|
+
and_then ||= options[:completion]
|
23
|
+
disconnect_block = options[:disconnect]
|
24
|
+
if disconnect || and_then.arity < 2
|
25
|
+
NSLog('Warning! The Firebase authWithCredential method is deprecated.')
|
26
|
+
NSLog('Instead of using a completion and cancel block, pass one block:')
|
27
|
+
NSLog('fb.auth(token) do |error, auth_data| .. end')
|
28
|
+
authWithCredential(token, withCompletionBlock:and_then, withCancelBlock: disconnect_block)
|
29
|
+
else
|
30
|
+
authWithCustomToken(token, withCompletionBlock: and_then)
|
31
|
+
end
|
32
|
+
return self
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.logout(&block)
|
36
|
+
Firebase.new.logout(&block)
|
37
|
+
end
|
38
|
+
def logout(&block)
|
39
|
+
if block_given?
|
40
|
+
unauthWithCompletionBlock(block)
|
41
|
+
else
|
42
|
+
unauth
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.authenticated?(&block)
|
47
|
+
Firebase.new.authenticated?(&block)
|
48
|
+
end
|
49
|
+
# checks the auth status. If you pass a block the observeAuthEventWithBlock
|
50
|
+
# is used to determine the status. If you don't pass a block, this method
|
51
|
+
# returns true or false.
|
52
|
+
def authenticated?(&block)
|
53
|
+
if block
|
54
|
+
observeAuthEventWithBlock(:value, block)
|
55
|
+
else
|
56
|
+
!!authData
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# You should call this when you no longer need `authenticated?` data.
|
61
|
+
def self.off_auth(handler)
|
62
|
+
Firebase.new.off_auth(handler)
|
63
|
+
end
|
64
|
+
def off_auth(handler)
|
65
|
+
removeAuthEventObserverWithHandle(handler)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.create_user(credentials, &block)
|
69
|
+
Firebase.new.create_user(credentials, &block)
|
70
|
+
end
|
71
|
+
def create_user(credentials, &block)
|
72
|
+
raise ":email is required in #{__method__}" unless credentials.key?(:email)
|
73
|
+
raise ":password is required in #{__method__}" unless credentials.key?(:password)
|
74
|
+
email = credentials[:email]
|
75
|
+
password = credentials[:password]
|
76
|
+
begin
|
77
|
+
createUserWithEmail(email, password: password, withCompletionBlock: block)
|
78
|
+
rescue RuntimeError => e
|
79
|
+
block.call(e, nil)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.create_user_and_login(credentials, &block)
|
84
|
+
Firebase.new.create_user_and_login(credentials, &block)
|
85
|
+
end
|
86
|
+
def create_user_and_login(credentials, &block)
|
87
|
+
raise ":email is required in #{__method__}" unless credentials.key?(:email)
|
88
|
+
raise ":password is required in #{__method__}" unless credentials.key?(:password)
|
89
|
+
email = credentials[:email]
|
90
|
+
password = credentials[:password]
|
91
|
+
begin
|
92
|
+
createUserWithEmail(email, password: password, withCompletionBlock: -> (error) do
|
93
|
+
if error
|
94
|
+
block.call(error, nil)
|
95
|
+
else
|
96
|
+
login(credentials, &block)
|
97
|
+
end
|
98
|
+
end)
|
99
|
+
rescue RuntimeError => e
|
100
|
+
block.call(e, nil)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.update_user(credentials, &block)
|
105
|
+
Firebase.new.update_user(credentials, &block)
|
106
|
+
end
|
107
|
+
def update_user(credentials, &block)
|
108
|
+
raise ":email is required in #{__method__}" unless credentials.key?(:email)
|
109
|
+
raise ":old_password is required in #{__method__}" unless credentials.key?(:old_password)
|
110
|
+
raise ":new_password is required in #{__method__}" unless credentials.key?(:new_password)
|
111
|
+
email = credentials[:email]
|
112
|
+
old_password = credentials[:old_password]
|
113
|
+
new_password = credentials[:new_password]
|
114
|
+
changePasswordForUser(email, fromOld: old_password, toNew: new_password, withCompletionBlock: block)
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.send_password_reset(credentials, &block)
|
118
|
+
Firebase.new.send_password_reset(credentials, &block)
|
119
|
+
end
|
120
|
+
def send_password_reset(email, &block)
|
121
|
+
resetPasswordForUser(email, withCompletionBlock: block)
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.remove_user(credentials, &block)
|
125
|
+
Firebase.new.remove_user(credentials, &block)
|
126
|
+
end
|
127
|
+
def remove_user(credentials, &block)
|
128
|
+
raise ":email is required in #{__method__}" unless credentials.key?(:email)
|
129
|
+
raise ":password is required in #{__method__}" unless credentials.key?(:password)
|
130
|
+
email = credentials[:email]
|
131
|
+
password = credentials[:password]
|
132
|
+
removeUser(email, password: password, withCompletionBlock: block)
|
133
|
+
end
|
134
|
+
|
135
|
+
def login_anonymously(&block)
|
136
|
+
authAnonymouslyWithCompletionBlock(block)
|
137
|
+
end
|
138
|
+
|
139
|
+
def login(credentials, &block)
|
140
|
+
raise ":email is required in #{__method__}" unless credentials.key?(:email)
|
141
|
+
raise ":password is required in #{__method__}" unless credentials.key?(:password)
|
142
|
+
email = credentials[:email]
|
143
|
+
password = credentials[:password]
|
144
|
+
begin
|
145
|
+
authUser(email, password: password, withCompletionBlock: block)
|
146
|
+
rescue RuntimeError => e
|
147
|
+
block.call(e, nil)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def login_to_oauth(provider, parameters={}, &block)
|
152
|
+
if parameters.is_a?(NSString)
|
153
|
+
token = parameters
|
154
|
+
elsif parameters.key?(:token)
|
155
|
+
token = parameters[:token]
|
156
|
+
else
|
157
|
+
token = nil
|
158
|
+
end
|
159
|
+
|
160
|
+
if token
|
161
|
+
authWithOAuthProvider(provider, token: token, withCompletionBlock: block)
|
162
|
+
else
|
163
|
+
objc_params = {}
|
164
|
+
parameters.each do |key, value|
|
165
|
+
# explicitly convert :sym to 'sym'
|
166
|
+
objc_params[key.to_s] = value
|
167
|
+
end
|
168
|
+
authWithOAuthProvider(provider, parameters: objc_params, withCompletionBlock: block)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def login_to_facebook(credentials, &block)
|
173
|
+
if credentials.is_a?(NSString)
|
174
|
+
token = credentials
|
175
|
+
else
|
176
|
+
token = credentials[:token]
|
177
|
+
end
|
178
|
+
raise ":token is required in #{__method__}" unless token
|
179
|
+
|
180
|
+
authWithOAuthProvider('facebook', token: token, withCompletionBlock: block)
|
181
|
+
end
|
182
|
+
|
183
|
+
def login_to_twitter(credentials, &block)
|
184
|
+
oauth_token = credentials[:token] || credentials[:oauth_token]
|
185
|
+
oauth_token_secret = credentials[:secret] || credentials[:oauth_token_secret]
|
186
|
+
raise ":token is required in #{__method__}" unless oauth_token
|
187
|
+
raise ":secret is required in #{__method__}" unless oauth_token_secret
|
188
|
+
|
189
|
+
provider = 'twitter'
|
190
|
+
options = {
|
191
|
+
'oauth_token' => oauth_token,
|
192
|
+
'oauth_token_secret' => oauth_token_secret,
|
193
|
+
}
|
194
|
+
login_to_oauth(provider, options, &block)
|
195
|
+
end
|
196
|
+
|
197
|
+
def login_to_github(credentials, &block)
|
198
|
+
if credentials.is_a?(NSString)
|
199
|
+
token = credentials
|
200
|
+
else
|
201
|
+
token = credentials[:token]
|
202
|
+
end
|
203
|
+
raise ":token is required in #{__method__}" unless token
|
204
|
+
|
205
|
+
authWithOAuthProvider('github', token: token, withCompletionBlock: block)
|
206
|
+
end
|
207
|
+
|
208
|
+
def login_to_google(credentials, &block)
|
209
|
+
if credentials.is_a?(NSString)
|
210
|
+
token = credentials
|
211
|
+
else
|
212
|
+
token = credentials[:token]
|
213
|
+
end
|
214
|
+
raise ":token is required in #{__method__}" unless token
|
215
|
+
|
216
|
+
authWithOAuthProvider('google', token: token, withCompletionBlock: block)
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# see https://www.firebase.com/docs/ios/guide/login/facebook.html for more info
|
2
|
+
# (that's where this code came from)
|
3
|
+
class Firebase
|
4
|
+
def self.open_facebook_session(options={}, &block)
|
5
|
+
self.new.open_facebook_session(options={}, &block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def open_facebook_session(options={}, &block)
|
9
|
+
ref = self
|
10
|
+
permissions = options[:permissions] || ['public_profile']
|
11
|
+
allow_ui = options.fetch(:allow_login_ui, true)
|
12
|
+
FBSession.openActiveSessionWithReadPermissions(permissions, allowLoginUI: allow_ui,
|
13
|
+
completionHandler: -> (session, state, error) do
|
14
|
+
if error
|
15
|
+
block.call(error, nil)
|
16
|
+
elsif state == FBSessionStateOpen
|
17
|
+
token = session.accessTokenData.accessToken
|
18
|
+
|
19
|
+
ref.authWithOAuthProvider('facebook', token:token, withCompletionBlock:block)
|
20
|
+
end
|
21
|
+
end)
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# see https://www.firebase.com/docs/ios/guide/login/github.html for more info
|
2
|
+
# (that's where this code came from)
|
3
|
+
class Firebase
|
4
|
+
def self.github_token=(value)
|
5
|
+
@github_token = value
|
6
|
+
end
|
7
|
+
def self.github_token
|
8
|
+
@github_token
|
9
|
+
end
|
10
|
+
def self.open_github_session(options={}, &block)
|
11
|
+
self.new.open_github_session(options={}, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def open_github_session(options={}, &block)
|
15
|
+
ref = self
|
16
|
+
token = options[:token] || Firebase.github_token
|
17
|
+
raise "token is required in #{__method__}" unless token
|
18
|
+
firebase_ref.login_to_github('github', token)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
# see https://www.firebase.com/docs/ios/guide/login/twitter.html for more info
|
2
|
+
# (that's where this code came from)
|
3
|
+
class Firebase
|
4
|
+
def self.twitter_api_key=(value)
|
5
|
+
@twitter_api_key = value
|
6
|
+
end
|
7
|
+
def self.twitter_api_key
|
8
|
+
@twitter_api_key
|
9
|
+
end
|
10
|
+
def self.open_twitter_session(options={}, &block)
|
11
|
+
self.new.open_twitter_session(options={}, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def open_twitter_session(options={}, &block)
|
15
|
+
ref = self
|
16
|
+
api_key = options[:api_key] || Firebase.twitter_api_key
|
17
|
+
raise "api_key is required in #{__method__}" unless api_key
|
18
|
+
|
19
|
+
helper = Motion::Firebase::TwitterAuthHelper.new(ref, api_key)
|
20
|
+
helper.select_twitter_account(&block)
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
module Motion
|
27
|
+
module Firebase
|
28
|
+
class TwitterAuthHelper
|
29
|
+
|
30
|
+
def initialize(ref, api_key)
|
31
|
+
@store = ACAccountStore.new
|
32
|
+
@ref = ref
|
33
|
+
@api_key = api_key
|
34
|
+
@account = nil
|
35
|
+
@acounts = nil
|
36
|
+
@firebase_callback = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
# Step 1a -- get account
|
40
|
+
def select_twitter_account(&callback)
|
41
|
+
account_type = @store.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)
|
42
|
+
|
43
|
+
@store.requestAccessToAccountsWithType(account_type, options: nil, completion: -> (granted, error) do
|
44
|
+
if granted
|
45
|
+
@accounts = @store.accountsWithAccountType(account_type)
|
46
|
+
if @accounts.length > 0
|
47
|
+
Dispatch::Queue.main.async do
|
48
|
+
next_step = -> (account, &firebase_handler) do
|
49
|
+
self.authenticate_account(account, &firebase_handler)
|
50
|
+
end
|
51
|
+
callback.call(nil, @accounts, next_step)
|
52
|
+
end if callback
|
53
|
+
else
|
54
|
+
error = NSError.alloc.initWithDomain('TwitterAuthHelper',
|
55
|
+
code: AuthHelperErrorAccountAccessDenied,
|
56
|
+
userInfo: { NSLocalizedDescriptionKey => 'No Twitter accounts detected on phone. Please add one in the settings first.' })
|
57
|
+
Dispatch::Queue.main.async do
|
58
|
+
callback.call(error, nil, nil)
|
59
|
+
end if callback
|
60
|
+
end
|
61
|
+
else
|
62
|
+
error = NSError.alloc.initWithDomain('TwitterAuthHelper',
|
63
|
+
code: AuthHelperErrorAccountAccessDenied,
|
64
|
+
userInfo: { NSLocalizedDescriptionKey => 'Access to twitter accounts denied.' })
|
65
|
+
Dispatch::Queue.main.async do
|
66
|
+
callback.call(error, nil, nil)
|
67
|
+
end if callback
|
68
|
+
end
|
69
|
+
end)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Last public facing method
|
73
|
+
def authenticate_account(account, &firebase_handler)
|
74
|
+
if !account
|
75
|
+
error = NSError.alloc.initWithDomain('TwitterAuthHelper',
|
76
|
+
code: AuthHelperErrorAccountAccessDenied,
|
77
|
+
userInfo: { NSLocalizedDescriptionKey => 'No Twitter account to authenticate.' })
|
78
|
+
Dispatch::Queue.main.async do
|
79
|
+
firebase_handler.call(error, nil)
|
80
|
+
end if firebase_handler
|
81
|
+
else
|
82
|
+
@account = account
|
83
|
+
@firebase_callback = firebase_handler
|
84
|
+
make_reverse_request # kick off step 1b
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def callback_if_exists_with_error(error)
|
89
|
+
if @firebase_callback
|
90
|
+
Dispatch::Queue.main.async do
|
91
|
+
@firebase_callback.call(error, nil)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Step 1b -- get request token from Twitter
|
97
|
+
def make_reverse_request
|
98
|
+
@ref.makeReverseOAuthRequestTo('twitter', withCompletionBlock: -> (error, json) do
|
99
|
+
if error
|
100
|
+
callback_if_exists_with_error(error)
|
101
|
+
else
|
102
|
+
request = create_credential_request_with_reverse_auth_payload(json)
|
103
|
+
request_twitter_credentials(request)
|
104
|
+
end
|
105
|
+
end)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Step 1b Helper -- creates request to Twitter
|
109
|
+
def create_credential_request_with_reverse_auth_payload(json)
|
110
|
+
params = {}
|
111
|
+
|
112
|
+
request_token = json['auth']
|
113
|
+
params['x_reverse_auth_parameters'] = request_token
|
114
|
+
params['x_reverse_auth_target'] = @api_key
|
115
|
+
|
116
|
+
url = NSURL.URLWithString('https://api.twitter.com/oauth/access_token')
|
117
|
+
req = SLRequest.requestForServiceType(SLServiceTypeTwitter, requestMethod: SLRequestMethodPOST, URL: url, parameters: params)
|
118
|
+
req.setAccount(@account)
|
119
|
+
|
120
|
+
req
|
121
|
+
end
|
122
|
+
|
123
|
+
# Step 2 -- request credentials from Twitter
|
124
|
+
def request_twitter_credentials(request)
|
125
|
+
request.performRequestWithHandler(-> (response_data, url_response, error) do
|
126
|
+
if error
|
127
|
+
callback_if_exists_with_error(error)
|
128
|
+
else
|
129
|
+
authenticate_with_twitter_credentials(response_data)
|
130
|
+
end
|
131
|
+
end)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Step 3 -- authenticate with Firebase using Twitter credentials
|
135
|
+
def authenticate_with_twitter_credentials(response_data)
|
136
|
+
params = parse_twitter_credentials(response_data)
|
137
|
+
if params['error']
|
138
|
+
error = NSError.alloc.initWithDomain('TwitterAuthHelper',
|
139
|
+
code: AuthHelperErrorOAuthTokenRequestDenied,
|
140
|
+
userInfo: { NSLocalizedDescriptionKey => 'OAuth token request was denied.',
|
141
|
+
'details' => params['error']})
|
142
|
+
callback_if_exists_with_error(error)
|
143
|
+
else
|
144
|
+
@ref.authWithOAuthProvider('twitter', parameters: params, withCompletionBlock: @firebase_callback)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Step 3 Helper -- parsers credentials into dictionary
|
149
|
+
def parse_twitter_credentials(response_data)
|
150
|
+
account_data = NSString.alloc.initWithData(response_data, encoding:NSUTF8StringEncoding)
|
151
|
+
params = {}
|
152
|
+
|
153
|
+
account_data.split('&').each do |param|
|
154
|
+
key, value = param.split('=')
|
155
|
+
params[key] = value
|
156
|
+
end
|
157
|
+
|
158
|
+
# This is super fragile error handling, but basically check that the token and token secret are there.
|
159
|
+
# If not, return the result that Twitter returned.
|
160
|
+
if params['oauth_token_secret'] && params['oauth_token']
|
161
|
+
params
|
162
|
+
else
|
163
|
+
{ 'error': account_data }
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|