motion-firebase 2.1.5 → 3.0.0

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.
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