001package com.gigya.android.sdk.api;
002
003import android.support.annotation.NonNull;
004
005import com.gigya.android.sdk.GigyaCallback;
006import com.gigya.android.sdk.GigyaDefinitions;
007import com.gigya.android.sdk.GigyaLogger;
008import com.gigya.android.sdk.GigyaLoginCallback;
009import com.gigya.android.sdk.account.IAccountService;
010import com.gigya.android.sdk.account.models.GigyaAccount;
011import com.gigya.android.sdk.interruption.IInterruptionResolverFactory;
012import com.gigya.android.sdk.interruption.tfa.models.TFAProvidersModel;
013import com.gigya.android.sdk.network.GigyaError;
014import com.gigya.android.sdk.network.adapter.RestAdapter;
015import com.gigya.android.sdk.providers.IProviderFactory;
016import com.gigya.android.sdk.providers.IProviderPermissionsCallback;
017import com.gigya.android.sdk.providers.provider.IProvider;
018import com.gigya.android.sdk.providers.provider.ProviderCallback;
019import com.gigya.android.sdk.session.ISessionService;
020import com.gigya.android.sdk.session.SessionInfo;
021import com.gigya.android.sdk.utils.DeviceUtils;
022import com.gigya.android.sdk.utils.ObjectUtils;
023import com.google.gson.Gson;
024
025import java.util.HashMap;
026import java.util.Map;
027
028/**
029 * Service responsible for sending and processing pre-defined API requests
030 *
031 * @param <A> Typed account instance (extends GigyaAccount).
032 */
033public class BusinessApiService<A extends GigyaAccount> implements IBusinessApiService<A> {
034
035    private static final String LOG_TAG = "BusinessApiService";
036
037    // Dependencies.
038    final protected ISessionService _sessionService;
039    final private IAccountService<A> _accountService;
040    final private IApiService _apiService;
041    final private IApiRequestFactory _reqFactory;
042    final private IProviderFactory _providerFactory;
043    final private IInterruptionResolverFactory _interruptionsHandler;
044
045    public BusinessApiService(ISessionService sessionService,
046                              IAccountService<A> accountService,
047                              IApiService apiService,
048                              IApiRequestFactory requestFactory,
049                              IProviderFactory providerFactory,
050                              IInterruptionResolverFactory interruptionsHandler) {
051        _sessionService = sessionService;
052        _accountService = accountService;
053        _apiService = apiService;
054        _reqFactory = requestFactory;
055        _providerFactory = providerFactory;
056        _interruptionsHandler = interruptionsHandler;
057    }
058
059
060    //region CONDITIONALS & HELPERS
061
062    private void updateWithNewSession(GigyaApiResponse apiResponse) {
063        if (apiResponse.containsNested("sessionInfo.sessionSecret")) {
064            final SessionInfo newSession = apiResponse.getField("sessionInfo", SessionInfo.class);
065            _sessionService.setSession(newSession);
066            _accountService.invalidateAccount();
067        }
068    }
069
070    private void updateCachedAccount(GigyaApiResponse apiResponse) {
071        _accountService.setAccount(apiResponse.asJson());
072    }
073
074    private void handleAccountApiResponse(GigyaApiResponse response, GigyaLoginCallback<A> loginCallback) {
075        final int errorCode = response.getErrorCode();
076        if (errorCode != 0) {
077            // Handle interruption.
078            if (loginCallback != null) {
079                _interruptionsHandler.resolve(response, loginCallback);
080            }
081        } else {
082            // Parse & success.
083            A parsed = response.parseTo(_accountService.getAccountSchema());
084            updateWithNewSession(response);
085            updateCachedAccount(response);
086            if (loginCallback != null) {
087                loginCallback.onSuccess(parsed);
088            }
089        }
090    }
091
092    //endregion
093
094    //region SEND REQUEST
095
096    /**
097     * Base API send request initiator.
098     *
099     * @param api           Requested API.
100     * @param params        Requested parameters map.
101     * @param requestMethod HTTP request method {@link RestAdapter}
102     * @param clazz         Requested Typed response class.
103     * @param gigyaCallback Response callback.
104     * @param <V>           Typed response class.
105     */
106    @Override
107    public <V> void send(String api, Map<String, Object> params, int requestMethod, final Class<V> clazz, final GigyaCallback<V> gigyaCallback) {
108        final GigyaApiRequest request = _reqFactory.create(api, params, RestAdapter.HttpMethod.fromInt(requestMethod));
109        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
110            @Override
111            public void onApiSuccess(GigyaApiResponse response) {
112                if (response.getErrorCode() == 0) {
113                    if (clazz == GigyaApiResponse.class) {
114                        gigyaCallback.onSuccess((V) response);
115                    } else {
116                        V parsed = response.parseTo(clazz);
117                        gigyaCallback.onSuccess(parsed);
118                    }
119                } else {
120                    gigyaCallback.onError(GigyaError.fromResponse(response));
121                }
122            }
123
124            @Override
125            public void onApiError(GigyaError gigyaError) {
126                gigyaCallback.onError(gigyaError);
127            }
128        });
129    }
130
131    //endregion
132
133    //region LOGOUT
134
135    /**
136     * Request to log out of the current active session.
137     *
138     * @see <a href="https://developers.gigya.com/display/GD/accounts.logout+REST">accounts.logout REST</a>
139     */
140    @Override
141    public void logout(final GigyaCallback<GigyaApiResponse> gigyaCallback) {
142        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_LOGOUT, null, RestAdapter.HttpMethod.GET);
143        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
144
145            @Override
146            public void onApiSuccess(GigyaApiResponse response) {
147                GigyaLogger.error(LOG_TAG, "logOut: Success");
148                if (gigyaCallback != null) {
149                    gigyaCallback.onSuccess(response);
150                }
151
152            }
153
154            @Override
155            public void onApiError(GigyaError gigyaError) {
156                GigyaLogger.error(LOG_TAG, "logOut: Failed");
157                if (gigyaCallback != null) {
158                    gigyaCallback.onError(gigyaError);
159                }
160            }
161        });
162    }
163
164    //endregion
165
166    //region LOGIN
167
168    /**
169     * Request login given map of parameters.
170     *
171     * @param params             Parameter map
172     * @param gigyaLoginCallback Login response callback.
173     * @see <a href="https://developers.gigya.com/display/GD/accounts.login+REST">accounts.login REST</a>
174     */
175    @Override
176    public void login(Map<String, Object> params, final GigyaLoginCallback<A> gigyaLoginCallback) {
177        if (!params.containsKey("include")) {
178            // If include field is not present add default fields.
179            params.put("include", "profile,data,subscriptions,preferences");
180        }
181        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_LOGIN, params, RestAdapter.HttpMethod.POST);
182        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
183            @Override
184            public void onApiSuccess(GigyaApiResponse response) {
185                handleAccountApiResponse(response, gigyaLoginCallback);
186            }
187
188            @Override
189            public void onApiError(GigyaError gigyaError) {
190                gigyaLoginCallback.onError(gigyaError);
191            }
192        });
193    }
194
195    /**
196     * Request login to specific social provider.
197     * Will begin a login flow comprised of two steps.
198     * 1. Social login with provider.
199     * 2. Login with the Gigya server.
200     *
201     * @param socialProvider     Requested social provider   {@link GigyaDefinitions.Providers}
202     * @param params             Request parameters.
203     * @param gigyaLoginCallback Login response callback.
204     */
205    @Override
206    public void login(@GigyaDefinitions.Providers.SocialProvider String socialProvider, Map<String, Object> params, final GigyaLoginCallback<A> gigyaLoginCallback) {
207        params.put("provider", socialProvider);  // Needed for non native providers.
208
209        IProvider provider = _providerFactory.providerFor(socialProvider, new ProviderCallback() {
210            @Override
211            public void onProviderSession(String providerName, SessionInfo sessionInfo, Runnable completionHandler) {
212                if (gigyaLoginCallback != null) {
213                    gigyaLoginCallback.onIntermediateLoad();
214                }
215                // Set new session.
216                _sessionService.setSession(sessionInfo);
217                completionHandler.run();
218                // Force fetch account.
219                _accountService.invalidateAccount();
220                getAccount(gigyaLoginCallback);
221            }
222
223            @Override
224            public void onProviderSessions(Map<String, Object> loginParams, Runnable completionHandler) {
225                if (gigyaLoginCallback != null) {
226                    gigyaLoginCallback.onIntermediateLoad();
227                }
228                notifyNativeSocialLogin(loginParams, gigyaLoginCallback, completionHandler);
229            }
230
231            @Override
232            public void onCanceled() {
233                if (gigyaLoginCallback != null) {
234                    gigyaLoginCallback.onOperationCanceled();
235                }
236            }
237
238            @Override
239            public void onError(GigyaApiResponse response) {
240                handleAccountApiResponse(response, gigyaLoginCallback);
241            }
242        });
243
244        if (params.containsKey("regToken")) {
245            final String regToken = (String) params.get("regToken");
246            provider.setRegToken(regToken);
247        }
248        String loginMode = "standard";
249        if (params.containsKey("loginMode")) {
250            loginMode = (String) params.get("loginMode");
251        }
252
253        // Perform provider login.
254        provider.login(params, loginMode);
255    }
256
257    /**
258     * Request to verify the current session state.
259     *
260     * @param UID           Current user UID.
261     * @param gigyaCallback Response callback.
262     * @see <a href="https://developers.gigya.com/display/GD/accounts.verifyLogin+REST">accounts.verifyLogin REST</a>
263     */
264    @Override
265    public void verifyLogin(String UID, final GigyaCallback<A> gigyaCallback) {
266        if (!_sessionService.isValid()) {
267            GigyaLogger.error(LOG_TAG, "Action requires a valid session");
268            if (gigyaCallback != null) {
269                gigyaCallback.onError(GigyaError.unauthorizedUser());
270            }
271        }
272        final Map<String, Object> params = new HashMap<>();
273        if (UID != null) {
274            params.put("UID", UID);
275        }
276        if (!params.containsKey("include")) {
277            // If include field is not present add default fields.
278            params.put("include", "identities-all,loginIDs,profile,email,data");
279        }
280        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_VERIFY_LOGIN, params, RestAdapter.HttpMethod.POST);
281        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
282            @Override
283            public void onApiSuccess(GigyaApiResponse response) {
284                if (response.getErrorCode() == 0) {
285                    // No interruption support.
286                    A parsed = response.parseTo(_accountService.getAccountSchema());
287                    updateWithNewSession(response);
288                    updateCachedAccount(response);
289                    gigyaCallback.onSuccess(parsed);
290                } else {
291                    gigyaCallback.onError(GigyaError.fromResponse(response));
292                }
293            }
294
295            @Override
296            public void onApiError(GigyaError gigyaError) {
297                gigyaCallback.onError(gigyaError);
298            }
299        });
300    }
301
302    /**
303     * Login to with social provider when the provider session is available (obtained via specific provider login process).
304     *
305     * @param params                    Request parameters/
306     * @param gigyaLoginCallback        Login response callback.
307     * @param optionalCompletionHandler additional completion handler Runnable.
308     */
309    @Override
310    public void notifyNativeSocialLogin(Map<String, Object> params, final GigyaLoginCallback<A> gigyaLoginCallback, final Runnable optionalCompletionHandler) {
311        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_NOTIFY_SOCIAL_LOGIN, params, RestAdapter.HttpMethod.POST);
312        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
313            @Override
314            public void onApiSuccess(GigyaApiResponse response) {
315                if (response.getErrorCode() == 0) {
316                    updateWithNewSession(response); // Update with new session.
317                    getAccount(gigyaLoginCallback); // Request account details. Will need to change when the endpoint will be completed.
318                    if (optionalCompletionHandler != null) {
319                        optionalCompletionHandler.run();
320                    }
321                } else {
322                    handleAccountApiResponse(response, gigyaLoginCallback);
323                }
324            }
325
326            @Override
327            public void onApiError(GigyaError gigyaError) {
328                gigyaLoginCallback.onError(gigyaError);
329            }
330        });
331    }
332
333    //endregion
334
335    //region REGISTER
336
337    /**
338     * Finalize current registration process.
339     *
340     * @param params             Request parameters.
341     * @param gigyaLoginCallback Login response callback.
342     * @see <a href="https://developers.gigya.com/display/GD/accounts.finalizeRegistration+REST">accounts.finalizeRegistration REST</a>
343     */
344    @Override
345    public void finalizeRegistration(Map<String, Object> params, final GigyaLoginCallback<A> gigyaLoginCallback) {
346        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_FINALIZE_REGISTRATION, params, RestAdapter.HttpMethod.POST);
347        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
348            @Override
349            public void onApiSuccess(GigyaApiResponse response) {
350                handleAccountApiResponse(response, gigyaLoginCallback);
351            }
352
353            @Override
354            public void onApiError(GigyaError gigyaError) {
355                gigyaLoginCallback.onError(gigyaError);
356            }
357        });
358    }
359
360    /**
361     * Register request given map of parameters.
362     * Login flow is composed of two stages:
363     * 1. Request to initialize the registration process.
364     * 2. Actual registration process using the registration token obtained from previous request.
365     * NOTE: registration set to finalize by default thus not requiring a call to finalize the registration.
366     *
367     * @param params             Request parameters.
368     * @param gigyaLoginCallback Login response callback.
369     * @see <a href="https://developers.gigya.com/display/GD/accounts.initRegistration+REST">accounts.initRegistration REST</a>
370     * @see <a href="https://developers.gigya.com/display/GD/accounts.register+REST">accounts.register REST</a>
371     */
372    @Override
373    public void register(final Map<String, Object> params, final GigyaLoginCallback<A> gigyaLoginCallback) {
374        // #1 Chain init registration.
375        final GigyaApiRequest initRequest = _reqFactory.create(GigyaDefinitions.API.API_INIT_REGISTRATION, params, RestAdapter.HttpMethod.POST);
376        _apiService.send(initRequest, false, new ApiService.IApiServiceResponse() {
377            @Override
378            public void onApiSuccess(GigyaApiResponse response) {
379                if (response.getErrorCode() == 0) {
380                    final String regToken = response.getField("regToken", String.class);
381                    if (regToken != null) {
382                        params.put("regToken", regToken);
383                        params.put("finalizeRegistration", true);
384                    } else {
385                        GigyaLogger.error(LOG_TAG, "register: Init registration produced null regToken");
386                        gigyaLoginCallback.onError(GigyaError.generalError());
387                        return;
388                    }
389                    // #2 Chain login.
390                    GigyaApiRequest regRequest = _reqFactory.create(GigyaDefinitions.API.API_REGISTER, params, RestAdapter.HttpMethod.POST);
391                    _apiService.send(regRequest, false, new ApiService.IApiServiceResponse() {
392                        @Override
393                        public void onApiSuccess(GigyaApiResponse response) {
394                            handleAccountApiResponse(response, gigyaLoginCallback);
395                        }
396
397                        @Override
398                        public void onApiError(GigyaError gigyaError) {
399                            gigyaLoginCallback.onError(gigyaError);
400                        }
401                    });
402                } else {
403                    gigyaLoginCallback.onError(GigyaError.fromResponse(response));
404                }
405            }
406
407            @Override
408            public void onApiError(GigyaError gigyaError) {
409                gigyaLoginCallback.onError(gigyaError);
410            }
411        });
412    }
413
414    //endregion
415
416    //region ACCOUNT
417
418    /**
419     * Request account info for current active session.
420     *
421     * @param gigyaCallback Response callback.
422     * @see <a href="https://developers.gigya.com/display/GD/accounts.getAccountInfo+REST">accounts.getAccountInfo REST</a>
423     */
424    @Override
425    public void getAccount(final GigyaCallback<A> gigyaCallback) {
426        getAccount(null, gigyaCallback);
427    }
428
429    @Override
430    public void getAccount(@NonNull String[] include, @NonNull String[] profileExtraFields, GigyaCallback<A> gigyaCallback) {
431        final String includeParam = ObjectUtils.commaConcat(include);
432        final String profileExtraFieldsParam = ObjectUtils.commaConcat(profileExtraFields);
433        final Map<String, Object> params = new HashMap<>();
434        params.put("include", includeParam);
435        params.put("extraProfileFields", profileExtraFieldsParam);
436        getAccount(params, gigyaCallback);
437    }
438
439    @Override
440    public void getAccount(final Map<String, Object> params, final GigyaCallback<A> gigyaCallback) {
441        if (gigyaCallback == null) {
442            // Callback restricted api call.
443            return;
444        }
445        if (!_sessionService.isValid()) {
446            GigyaLogger.error(LOG_TAG, "Action requires a valid session");
447            gigyaCallback.onError(GigyaError.unauthorizedUser());
448        }
449        // Fetch caching relevant fields from parameter map (if exist) null fields are viable.
450        final String include = params != null ? (String) params.get("include") : null;
451        final String profileExtraFields = params != null ? (String) params.get("extraProfileFields") : null;
452        if (_accountService.isCachedAccount(include, profileExtraFields)) {
453            gigyaCallback.onSuccess(_accountService.getAccount());
454            return;
455        }
456        _accountService.updateExtendedParametersRequest(include, profileExtraFields);
457        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_GET_ACCOUNT_INFO, params, RestAdapter.HttpMethod.POST);
458        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
459            @Override
460            public void onApiSuccess(GigyaApiResponse response) {
461                if (response.getErrorCode() == 0) {
462                    // Parse response & update account service.
463                    A parsed = response.parseTo(_accountService.getAccountSchema());
464                    updateCachedAccount(response);
465                    gigyaCallback.onSuccess(parsed);
466                } else {
467                    gigyaCallback.onError(GigyaError.fromResponse(response));
468                }
469            }
470
471            @Override
472            public void onApiError(GigyaError gigyaError) {
473                gigyaCallback.onError(gigyaError);
474            }
475        });
476    }
477
478    /**
479     * Request account update for current active session.
480     *
481     * @param updatedAccount Updated account instance.
482     * @param gigyaCallback  Response callback.
483     * @see <a href="https://developers.gigya.com/display/GD/accounts.setAccountInfo+REST">accounts.setAccountInfo REST</a>
484     */
485    @Override
486    public void setAccount(A updatedAccount, final GigyaCallback<A> gigyaCallback) {
487        if (gigyaCallback == null) {
488            // Callback restricted api call.
489            return;
490        }
491        if (!_sessionService.isValid()) {
492            GigyaLogger.error(LOG_TAG, "Action requires a valid session");
493            gigyaCallback.onError(GigyaError.unauthorizedUser());
494        }
495        final Map<String, Object> params = _accountService.calculateDiff(new Gson(), _accountService.getAccount(), updatedAccount);
496        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_SET_ACCOUNT_INFO, params, RestAdapter.HttpMethod.POST);
497        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
498            @Override
499            public void onApiSuccess(GigyaApiResponse response) {
500                if (response.getErrorCode() == 0) {
501                    // Invalidate cached account and call getAccount API.
502                    _accountService.invalidateAccount();
503                    getAccount(gigyaCallback);
504                } else {
505                    gigyaCallback.onError(GigyaError.fromResponse(response));
506                }
507            }
508
509            @Override
510            public void onApiError(GigyaError gigyaError) {
511                gigyaCallback.onError(gigyaError);
512            }
513        });
514    }
515
516
517    /**
518     * Request account update for current active session.
519     *
520     * @param params        Updated parameters.
521     * @param gigyaCallback Response callback.
522     * @see <a href="https://developers.gigya.com/display/GD/accounts.setAccountInfo+REST">accounts.setAccountInfo REST</a>
523     */
524    @Override
525    public void setAccount(Map<String, Object> params, final GigyaCallback<A> gigyaCallback) {
526        if (!_sessionService.isValid()) {
527            GigyaLogger.error(LOG_TAG, "Action requires a valid session");
528            if (gigyaCallback != null) {
529                gigyaCallback.onError(GigyaError.unauthorizedUser());
530            }
531        }
532        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_SET_ACCOUNT_INFO, params, RestAdapter.HttpMethod.POST);
533        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
534            @Override
535            public void onApiSuccess(GigyaApiResponse response) {
536                if (response.getErrorCode() == 0) {
537                    // Invalidate cached account and call getAccount API.
538                    _accountService.invalidateAccount();
539                    getAccount(gigyaCallback);
540                } else {
541                    gigyaCallback.onError(GigyaError.fromResponse(response));
542                }
543            }
544
545            @Override
546            public void onApiError(GigyaError gigyaError) {
547                gigyaCallback.onError(gigyaError);
548            }
549        });
550    }
551
552    //endregion
553
554    //region MISC
555
556    // Non documented. For SDK use only.
557    @Override
558    public void refreshNativeProviderSession(Map<String, Object> params, final IProviderPermissionsCallback providerPermissionsCallback) {
559        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_REFRESH_PROVIDER_SESSION, params, RestAdapter.HttpMethod.POST);
560        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
561            @Override
562            public void onApiSuccess(GigyaApiResponse response) {
563                if (response.getErrorCode() == 0) {
564                    _accountService.invalidateAccount();
565                    providerPermissionsCallback.granted();
566                } else {
567                    final GigyaError error = GigyaError.fromResponse(response);
568                    providerPermissionsCallback.failed(error.getLocalizedMessage());
569                }
570            }
571
572            @Override
573            public void onApiError(GigyaError gigyaError) {
574                providerPermissionsCallback.failed(gigyaError.getLocalizedMessage());
575            }
576        });
577    }
578
579    /**
580     * Issue a reset password request.
581     *
582     * @param callback Response callback.
583     * @see <a href="https://developers.gigya.com/display/GD/accounts.resetPassword+REST">accounts.resetPassword REST</a>
584     */
585    @Override
586    public void forgotPassword(Map<String, Object> params, final GigyaCallback<GigyaApiResponse> callback) {
587        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_RESET_PASSWORD, params, RestAdapter.HttpMethod.POST);
588        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
589            @Override
590            public void onApiSuccess(GigyaApiResponse response) {
591                if (response.getErrorCode() == 0) {
592                    callback.onSuccess(response);
593                } else {
594                    callback.onError(GigyaError.fromResponse(response));
595                }
596            }
597
598            @Override
599            public void onApiError(GigyaError gigyaError) {
600                callback.onError(gigyaError);
601            }
602        });
603    }
604
605    /**
606     * Request to add a social network connection to existing account.
607     * Completion of this request will result in an updated login session.
608     *
609     * @param socialProvider     Requested social provider.
610     * @param gigyaLoginCallback Login response callback.
611     */
612    @Override
613    public void addConnection(String socialProvider, final GigyaLoginCallback<A> gigyaLoginCallback) {
614        if (!_sessionService.isValid()) {
615            GigyaLogger.error(LOG_TAG, "Action requires a valid session");
616            if (gigyaLoginCallback != null) {
617                gigyaLoginCallback.onError(GigyaError.unauthorizedUser());
618            }
619        }
620        final Map<String, Object> params = new HashMap<>();
621        params.put("provider", socialProvider);  // Needed for non native providers.
622        IProvider provider = _providerFactory.providerFor(socialProvider, new ProviderCallback() {
623            @Override
624            public void onProviderSession(String providerName, SessionInfo sessionInfo, Runnable completionHandler) {
625                if (gigyaLoginCallback != null) {
626                    gigyaLoginCallback.onIntermediateLoad();
627                }
628
629                completionHandler.run();
630
631                // Force fetch account.
632                _accountService.invalidateAccount();
633                getAccount(gigyaLoginCallback);
634            }
635
636            @Override
637            public void onProviderSessions(Map<String, Object> loginParams, Runnable completionHandler) {
638                if (gigyaLoginCallback != null) {
639                    gigyaLoginCallback.onIntermediateLoad();
640                }
641                notifyNativeSocialLogin(loginParams, gigyaLoginCallback, completionHandler);
642            }
643
644            @Override
645            public void onCanceled() {
646                if (gigyaLoginCallback != null) {
647                    gigyaLoginCallback.onOperationCanceled();
648                }
649            }
650
651            @Override
652            public void onError(GigyaApiResponse response) {
653                handleAccountApiResponse(response, gigyaLoginCallback);
654            }
655        });
656
657        provider.login(params, "connect");
658    }
659
660    /**
661     * Request to remove a social network connection from existing account.
662     *
663     * @param socialProvider Requested social provider.
664     * @param gigyaCallback  Response callback.
665     * @see <a href="https://developers.gigya.com/display/GD/socialize.removeConnection+REST">socialize.removeConnection REST</a>
666     */
667    @Override
668    public void removeConnection(String socialProvider, final GigyaCallback<GigyaApiResponse> gigyaCallback) {
669        if (!_sessionService.isValid()) {
670            GigyaLogger.error(LOG_TAG, "Action requires a valid session");
671            if (gigyaCallback != null) {
672                gigyaCallback.onError(GigyaError.unauthorizedUser());
673            }
674        }
675        final Map<String, Object> params = new HashMap<>();
676        params.put("provider", socialProvider);
677        final String UID = _accountService.getAccount().getUID();
678        if (UID == null) {
679            GigyaLogger.error(LOG_TAG, "removeConnection: UID null. UID field is required to remove connection");
680            return;
681        }
682        params.put("UID", UID);
683        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_REMOVE_CONNECTION, params, RestAdapter.HttpMethod.POST);
684        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
685            @Override
686            public void onApiSuccess(GigyaApiResponse response) {
687                if (response.getErrorCode() == 0) {
688                    gigyaCallback.onSuccess(response);
689                } else {
690                    gigyaCallback.onError(GigyaError.fromResponse(response));
691                }
692            }
693
694            @Override
695            public void onApiError(GigyaError gigyaError) {
696                gigyaCallback.onError(gigyaError);
697            }
698        });
699    }
700
701    //endregion
702
703    //region INTERRUPTIONS RELATED
704
705    @Override
706    public void getConflictingAccounts(final String regToken, final GigyaCallback<GigyaApiResponse> callback) {
707        final Map<String, Object> params = new HashMap<>();
708        params.put("regToken", regToken);
709        final GigyaApiRequest request = _reqFactory.create(GigyaDefinitions.API.API_GET_CONFLICTING_ACCOUNTS, params, RestAdapter.HttpMethod.POST);
710        _apiService.send(request, false, new ApiService.IApiServiceResponse() {
711            @Override
712            public void onApiSuccess(GigyaApiResponse response) {
713                callback.onSuccess(response);
714            }
715
716            @Override
717            public void onApiError(GigyaError gigyaError) {
718                callback.onError(gigyaError);
719            }
720        });
721    }
722
723    @Override
724    public void getTFAProviders(String regToken, final GigyaCallback<TFAProvidersModel> callback) {
725        final Map<String, Object> params = new HashMap<>();
726        params.put("regToken", regToken);
727        send(GigyaDefinitions.API.API_TFA_GET_PROVIDERS, params, RestAdapter.GET, TFAProvidersModel.class, callback);
728    }
729
730    //endregion
731
732    //region AUTH RELATED
733
734    @Override
735    public void updateDevice(@NonNull final String pushToken, @NonNull final GigyaCallback<GigyaApiResponse> gigyaCallback) {
736        if (!_sessionService.isValid()) {
737            gigyaCallback.onError(GigyaError.unauthorizedUser());
738            return;
739        }
740        final Map<String, Object> params = new HashMap<>();
741        params.put("platform", "android");
742        params.put("man", DeviceUtils.getManufacturer());
743        params.put("os", DeviceUtils.getOsVersion());
744        params.put("pushToken", pushToken);
745        send(GigyaDefinitions.API.API_AUTH_UPDATE_DEVICE, params, RestAdapter.POST, GigyaApiResponse.class, new GigyaCallback<GigyaApiResponse>() {
746            @Override
747            public void onSuccess(GigyaApiResponse obj) { gigyaCallback.onSuccess(obj); }
748
749            @Override
750            public void onError(GigyaError error) {
751                gigyaCallback.onError(error);
752            }
753        });
754    }
755
756    //endregion
757}