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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +192 -64
  3. data/lib/firebase-auth/firebase_simple_login.rb +0 -76
  4. data/lib/firebase/fdata_snapshot.rb +4 -0
  5. data/lib/firebase/firebase.rb +53 -42
  6. data/lib/firebase/firebase_auth.rb +219 -0
  7. data/lib/firebase/firebase_facebook_helper.rb +24 -0
  8. data/lib/firebase/firebase_github_helper.rb +20 -0
  9. data/lib/firebase/firebase_twitter_helper.rb +169 -0
  10. data/lib/firebase/fquery.rb +16 -4
  11. data/lib/firebase/version.rb +2 -1
  12. data/lib/motion-firebase-auth.rb +3 -11
  13. data/lib/motion-firebase.rb +3 -1
  14. metadata +6 -19
  15. data/lib/vendor/Firebase.framework/Firebase +0 -0
  16. data/lib/vendor/Firebase.framework/Versions/A/Firebase +0 -0
  17. data/lib/vendor/Firebase.framework/Versions/A/Headers/FDataSnapshot.h +0 -146
  18. data/lib/vendor/Firebase.framework/Versions/A/Headers/FEventType.h +0 -43
  19. data/lib/vendor/Firebase.framework/Versions/A/Headers/FMutableData.h +0 -139
  20. data/lib/vendor/Firebase.framework/Versions/A/Headers/FQuery.h +0 -229
  21. data/lib/vendor/Firebase.framework/Versions/A/Headers/FTransactionResult.h +0 -50
  22. data/lib/vendor/Firebase.framework/Versions/A/Headers/Firebase.h +0 -707
  23. data/lib/vendor/Firebase.framework/build-MacOSX/Firebase.framework.bridgesupport +0 -582
  24. data/lib/vendor/Firebase.framework/build-iPhoneSimulator/Firebase.framework.bridgesupport +0 -582
  25. data/lib/vendor/FirebaseSimpleLogin.framework/FirebaseSimpleLogin +0 -0
  26. data/lib/vendor/FirebaseSimpleLogin.framework/Versions/A/FirebaseSimpleLogin +0 -0
  27. data/lib/vendor/FirebaseSimpleLogin.framework/Versions/A/Headers/FATypes.h +0 -52
  28. data/lib/vendor/FirebaseSimpleLogin.framework/Versions/A/Headers/FAUser.h +0 -97
  29. data/lib/vendor/FirebaseSimpleLogin.framework/Versions/A/Headers/FirebaseSimpleLogin.h +0 -221
  30. data/lib/vendor/FirebaseSimpleLogin.framework/build-MacOSX/FirebaseSimpleLogin.framework.bridgesupport +0 -230
  31. data/lib/vendor/FirebaseSimpleLogin.framework/build-iPhoneSimulator/FirebaseSimpleLogin.framework.bridgesupport +0 -230
@@ -22,8 +22,41 @@ class Firebase
22
22
  return event_type
23
23
  end
24
24
 
25
- def self.new(url)
26
- alloc.initWithUrl(url)
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
- # @example
40
- # firebase = Firebase.new('http://..../')
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
- alias_method :old_unauth, :unauth
57
-
58
- def unauth(&block)
59
- if block_given?
60
- unauthWithCompletionBlock(block)
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
- old_unauth
85
+ self.root['.info/connected']
63
86
  end
64
87
  end
65
88
 
66
- def auth_state
67
- self.root['.info/authenticated']
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
- goOnline
96
+ def self.online!
97
+ Firebase.new.online!
80
98
  end
81
-
82
- def run(options={}, &transaction)
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