Commit 8cd2c74d authored by Tiago Cunha's avatar Tiago Cunha

Unrealm app the app

Unfortunately there's some push related work here
parent 399dce09
......@@ -166,6 +166,21 @@ public class MethodCallHelper {
.onSuccessTask(this::saveToken);
}
public Task<Void> loginWithLdap(final String username, final String password) {
return call("login", TIMEOUT_MS, () -> {
JSONObject param = new JSONObject();
param.put("ldap", true);
param.put("username", username);
param.put("ldapPass", password);
param.put("ldapOptions", new JSONObject());
return new JSONArray().put(param);
}).onSuccessTask(CONVERT_TO_JSON_OBJECT)
.onSuccessTask(task -> Task.forResult(task.getResult().getString("token")))
.onSuccessTask(this::saveToken);
}
/**
* Login with OAuth.
*/
......
......@@ -16,6 +16,7 @@ import hugo.weaving.DebugLog;
public abstract class AbstractWebViewFragment extends AbstractFragment
implements OnBackPressListener {
private boolean isSet = false;
private WebView webview;
private WebViewClient webviewClient = new WebViewClient() {
private boolean error;
......@@ -66,6 +67,10 @@ public abstract class AbstractWebViewFragment extends AbstractFragment
}
private void setupWebView() {
if (isSet) {
return;
}
WebSettings settings = webview.getSettings();
if (settings != null) {
settings.setJavaScriptEnabled(true);
......@@ -80,6 +85,8 @@ public abstract class AbstractWebViewFragment extends AbstractFragment
//refs: https://code.google.com/p/android/issues/detail?id=35288
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
isSet = true;
}
@Override
......@@ -92,6 +99,15 @@ public abstract class AbstractWebViewFragment extends AbstractFragment
}
}
protected WebView getWebview() {
if (webview == null) {
return null;
}
setupWebView();
return webview;
}
protected abstract void navigateToInitialPage(WebView webview);
protected void onPageLoaded(WebView webview, String url) {
......
......@@ -12,20 +12,22 @@ import org.json.JSONObject;
import java.nio.charset.Charset;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.fragment.AbstractWebViewFragment;
import chat.rocket.android.helper.LogIfError;
import chat.rocket.android.log.RCLog;
import chat.rocket.persistence.realm.models.ddp.RealmMeteorLoginServiceConfiguration;
import chat.rocket.persistence.realm.RealmStore;
import chat.rocket.core.models.LoginServiceConfiguration;
import chat.rocket.persistence.realm.repositories.RealmLoginServiceConfigurationRepository;
public abstract class AbstractOAuthFragment extends AbstractWebViewFragment {
public abstract class AbstractOAuthFragment extends AbstractWebViewFragment
implements OAuthContract.View {
private OAuthContract.Presenter presenter;
protected abstract String getOAuthServiceName();
protected String hostname;
private String url;
private boolean resultOK;
protected abstract String getOAuthServiceName();
private boolean resultOK;
protected abstract String generateURL(RealmMeteorLoginServiceConfiguration oauthConfig);
protected abstract String generateURL(LoginServiceConfiguration oauthConfig);
private boolean hasValidArgs(Bundle args) {
return args != null
......@@ -54,47 +56,28 @@ public abstract class AbstractOAuthFragment extends AbstractWebViewFragment {
}
hostname = args.getString("hostname");
RealmMeteorLoginServiceConfiguration oauthConfig =
RealmStore.get(hostname).executeTransactionForRead(realm ->
realm.where(RealmMeteorLoginServiceConfiguration.class)
.equalTo(RealmMeteorLoginServiceConfiguration.SERVICE, getOAuthServiceName())
.findFirst());
if (oauthConfig == null) {
throw new IllegalArgumentException(
"Invalid hostname given,");
}
url = generateURL(oauthConfig);
presenter = new OAuthPresenter(
new RealmLoginServiceConfigurationRepository(hostname),
new MethodCallHelper(getContext(), hostname)
);
}
@Override
protected void navigateToInitialPage(WebView webview) {
if (TextUtils.isEmpty(url)) {
finish();
return;
}
resultOK = false;
webview.loadUrl(url);
webview.addJavascriptInterface(new JSInterface(result -> {
// onPageFinish is called twice... Should ignore latter one.
if (resultOK) {
return;
}
if (result != null && result.optBoolean("setCredentialToken", false)) {
try {
final String credentialToken = result.getString("credentialToken");
final String credentialSecret = result.getString("credentialSecret");
public void onResume() {
super.onResume();
presenter.bindView(this);
presenter.loadService(getOAuthServiceName());
}
handleOAuthCallback(credentialToken, credentialSecret);
resultOK = true;
} catch (JSONException exception) {
RCLog.e(exception, "failed to parse OAuth result.");
}
}
@Override
public void onPause() {
presenter.release();
super.onPause();
}
onOAuthCompleted();
}), "_rocketchet_hook");
@Override
protected void navigateToInitialPage(WebView webview) {
}
@Override
......@@ -108,18 +91,58 @@ public abstract class AbstractOAuthFragment extends AbstractWebViewFragment {
}
}
private void handleOAuthCallback(final String credentialToken, final String credentialSecret) {
new MethodCallHelper(getContext(), hostname)
.loginWithOAuth(credentialToken, credentialSecret)
.continueWith(new LogIfError());
@Override
public void showService(LoginServiceConfiguration oauthConfig) {
url = generateURL(oauthConfig);
showWebView();
}
@Override
public void close() {
finish();
}
protected void onOAuthCompleted() {
@Override
public void showLoginDone() {
resultOK = true;
onOAuthCompleted();
}
@Override
public void showLoginError() {
onOAuthCompleted();
}
private void showWebView() {
if (TextUtils.isEmpty(url)) {
finish();
return;
}
final WebView webView = getWebview();
if (webView == null) {
finish();
return;
}
resultOK = false;
webView.loadUrl(url);
webView.addJavascriptInterface(new JSInterface(result -> {
// onPageFinish is called twice... Should ignore latter one.
if (resultOK) {
return;
}
presenter.login(result);
}), "_rocketchet_hook");
}
protected void onOAuthCompleted() {
}
private interface JSInterfaceCallback {
void hanldeResult(@Nullable JSONObject result);
void handleResult(@Nullable JSONObject result);
}
private static final class JSInterface {
......@@ -132,9 +155,9 @@ public abstract class AbstractOAuthFragment extends AbstractWebViewFragment {
@JavascriptInterface
public void handleConfig(String config) {
try {
jsInterfaceCallback.hanldeResult(new JSONObject(config));
jsInterfaceCallback.handleResult(new JSONObject(config));
} catch (Exception exception) {
jsInterfaceCallback.hanldeResult(null);
jsInterfaceCallback.handleResult(null);
}
}
}
......
package chat.rocket.android.fragment.oauth;
import chat.rocket.persistence.realm.models.ddp.RealmMeteorLoginServiceConfiguration;
import chat.rocket.core.models.LoginServiceConfiguration;
import okhttp3.HttpUrl;
public class FacebookOAuthFragment extends AbstractOAuthFragment {
......@@ -11,13 +11,13 @@ public class FacebookOAuthFragment extends AbstractOAuthFragment {
}
@Override
protected String generateURL(RealmMeteorLoginServiceConfiguration oauthConfig) {
protected String generateURL(LoginServiceConfiguration oauthConfig) {
return new HttpUrl.Builder().scheme("https")
.host("www.facebook.com")
.addPathSegment("v2.2")
.addPathSegment("dialog")
.addPathSegment("oauth")
.addQueryParameter("client_id", oauthConfig.getAppId())
.addQueryParameter("client_id", oauthConfig.getKey())
.addQueryParameter("redirect_uri", "https://" + hostname + "/_oauth/facebook?close")
.addQueryParameter("display", "popup")
.addQueryParameter("scope", "email")
......
package chat.rocket.android.fragment.oauth;
import chat.rocket.persistence.realm.models.ddp.RealmMeteorLoginServiceConfiguration;
import chat.rocket.core.models.LoginServiceConfiguration;
import okhttp3.HttpUrl;
public class GitHubOAuthFragment extends AbstractOAuthFragment {
......@@ -11,13 +11,13 @@ public class GitHubOAuthFragment extends AbstractOAuthFragment {
}
@Override
protected String generateURL(RealmMeteorLoginServiceConfiguration oauthConfig) {
protected String generateURL(LoginServiceConfiguration oauthConfig) {
return new HttpUrl.Builder().scheme("https")
.host("github.com")
.addPathSegment("login")
.addPathSegment("oauth")
.addPathSegment("authorize")
.addQueryParameter("client_id", oauthConfig.getClientId())
.addQueryParameter("client_id", oauthConfig.getKey())
.addQueryParameter("scope", "user:email")
.addQueryParameter("state", getStateString())
.build()
......
package chat.rocket.android.fragment.oauth;
import chat.rocket.persistence.realm.models.ddp.RealmMeteorLoginServiceConfiguration;
import chat.rocket.core.models.LoginServiceConfiguration;
import okhttp3.HttpUrl;
public class GoogleOAuthFragment extends AbstractOAuthFragment {
......@@ -11,14 +11,14 @@ public class GoogleOAuthFragment extends AbstractOAuthFragment {
}
@Override
protected String generateURL(RealmMeteorLoginServiceConfiguration oauthConfig) {
protected String generateURL(LoginServiceConfiguration oauthConfig) {
return new HttpUrl.Builder().scheme("https")
.host("accounts.google.com")
.addPathSegment("o")
.addPathSegment("oauth2")
.addPathSegment("auth")
.addQueryParameter("response_type", "code")
.addQueryParameter("client_id", oauthConfig.getClientId())
.addQueryParameter("client_id", oauthConfig.getKey())
.addQueryParameter("scope", "profile email")
.addQueryParameter("redirect_uri", "https://" + hostname + "/_oauth/google?close")
.addQueryParameter("state", getStateString())
......
package chat.rocket.android.fragment.oauth;
import org.json.JSONObject;
import chat.rocket.android.shared.BaseContract;
import chat.rocket.core.models.LoginServiceConfiguration;
public interface OAuthContract {
interface View extends BaseContract.View {
void showService(LoginServiceConfiguration oauthConfig);
void close();
void showLoginDone();
void showLoginError();
}
interface Presenter extends BaseContract.Presenter<View> {
void loadService(String serviceName);
void login(JSONObject credentialJsonObject);
}
}
package chat.rocket.android.fragment.oauth;
import io.reactivex.android.schedulers.AndroidSchedulers;
import org.json.JSONObject;
import chat.rocket.android.BackgroundLooper;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.helper.LogIfError;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.shared.BasePresenter;
import chat.rocket.core.repositories.LoginServiceConfigurationRepository;
public class OAuthPresenter extends BasePresenter<OAuthContract.View>
implements OAuthContract.Presenter {
private final LoginServiceConfigurationRepository loginServiceConfigurationRepository;
private final MethodCallHelper methodCallHelper;
public OAuthPresenter(LoginServiceConfigurationRepository loginServiceConfigurationRepository,
MethodCallHelper methodCallHelper) {
this.loginServiceConfigurationRepository = loginServiceConfigurationRepository;
this.methodCallHelper = methodCallHelper;
}
@Override
public void loadService(String serviceName) {
addSubscription(
loginServiceConfigurationRepository.getByName(serviceName)
.subscribeOn(AndroidSchedulers.from(BackgroundLooper.get()))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(optional -> {
if (optional.isPresent()) {
view.showService(optional.get());
} else {
view.close();
}
})
);
}
@Override
public void login(JSONObject credentialJsonObject) {
if (credentialJsonObject == null || !credentialJsonObject.optBoolean("setCredentialToken")) {
view.showLoginError();
return;
}
final String credentialToken = credentialJsonObject.optString("credentialToken");
final String credentialSecret = credentialJsonObject.optString("credentialSecret");
if (TextUtils.isEmpty(credentialToken) || TextUtils.isEmpty(credentialSecret)) {
view.showLoginError();
return;
}
view.showLoginDone();
methodCallHelper.loginWithOAuth(credentialToken, credentialSecret)
.continueWith(new LogIfError());
}
}
package chat.rocket.android.fragment.oauth;
import chat.rocket.persistence.realm.models.ddp.RealmMeteorLoginServiceConfiguration;
import chat.rocket.core.models.LoginServiceConfiguration;
public class TwitterOAuthFragment extends AbstractOAuthFragment {
......@@ -10,7 +10,7 @@ public class TwitterOAuthFragment extends AbstractOAuthFragment {
}
@Override
protected String generateURL(RealmMeteorLoginServiceConfiguration oauthConfig) {
protected String generateURL(LoginServiceConfiguration oauthConfig) {
return "https://" + hostname + "/_oauth/twitter/"
+ "?requestTokenAndRedirect=true&state=" + getStateString();
}
......
......@@ -25,7 +25,6 @@ abstract class AbstractServerConfigFragment extends AbstractFragment {
hostname = args.getString(LoginActivity.KEY_HOSTNAME);
if (TextUtils.isEmpty(hostname)) {
finish();
return;
}
}
......
package chat.rocket.android.fragment.server_config;
import java.util.List;
import chat.rocket.android.shared.BaseContract;
import chat.rocket.core.models.LoginServiceConfiguration;
public interface LoginContract {
interface View extends BaseContract.View {
void showLoader();
void hideLoader();
void showError(String message);
void showLoginServices(List<LoginServiceConfiguration> loginServiceList);
}
interface Presenter extends BaseContract.Presenter<View> {
void login(String username, String password);
}
}
......@@ -11,18 +11,21 @@ import java.util.HashMap;
import java.util.List;
import chat.rocket.android.R;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.layouthelper.oauth.OAuthProviderInfo;
import chat.rocket.android.log.RCLog;
import chat.rocket.persistence.realm.models.ddp.RealmMeteorLoginServiceConfiguration;
import chat.rocket.persistence.realm.RealmListObserver;
import chat.rocket.persistence.realm.RealmStore;
import chat.rocket.core.models.LoginServiceConfiguration;
import chat.rocket.persistence.realm.repositories.RealmLoginServiceConfigurationRepository;
import chat.rocket.persistence.realm.repositories.RealmPublicSettingRepository;
/**
* Login screen.
*/
public class LoginFragment extends AbstractServerConfigFragment {
private RealmListObserver<RealmMeteorLoginServiceConfiguration> authProvidersObserver;
public class LoginFragment extends AbstractServerConfigFragment implements LoginContract.View {
private LoginContract.Presenter presenter;
private View btnEmail;
private View waitingView;
@Override
protected int getLayout() {
......@@ -32,37 +35,22 @@ public class LoginFragment extends AbstractServerConfigFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
authProvidersObserver = RealmStore.get(hostname)
.createListObserver(realm -> realm.where(RealmMeteorLoginServiceConfiguration.class).findAll())
.setOnUpdateListener(this::onRenderAuthProviders);
presenter = new LoginPresenter(
new RealmLoginServiceConfigurationRepository(hostname),
new RealmPublicSettingRepository(hostname),
new MethodCallHelper(getContext(), hostname)
);
}
@Override
protected void onSetupView() {
final View btnEmail = rootView.findViewById(R.id.btn_login_with_email);
btnEmail = rootView.findViewById(R.id.btn_login_with_email);
final TextView txtUsername = (TextView) rootView.findViewById(R.id.editor_username);
final TextView txtPasswd = (TextView) rootView.findViewById(R.id.editor_passwd);
final View waitingView = rootView.findViewById(R.id.waiting);
btnEmail.setOnClickListener(view -> {
final CharSequence username = txtUsername.getText();
final CharSequence passwd = txtPasswd.getText();
if (TextUtils.isEmpty(username) || TextUtils.isEmpty(passwd)) {
return;
}
view.setEnabled(false);
waitingView.setVisibility(View.VISIBLE);
new MethodCallHelper(getContext(), hostname)
.loginWithEmail(username.toString(), passwd.toString())
.continueWith(task -> {
if (task.isFaulted()) {
showError(task.getError().getMessage());
view.setEnabled(true);
waitingView.setVisibility(View.GONE);
}
return null;
});
});
waitingView = rootView.findViewById(R.id.waiting);
btnEmail.setOnClickListener(
view -> presenter.login(txtUsername.getText().toString(), txtPasswd.getText().toString()));
final View btnUserRegistration = rootView.findViewById(R.id.btn_user_registration);
btnUserRegistration.setOnClickListener(view -> UserRegistrationDialogFragment.create(hostname,
......@@ -70,11 +58,25 @@ public class LoginFragment extends AbstractServerConfigFragment {
.show(getFragmentManager(), UserRegistrationDialogFragment.class.getSimpleName()));
}
private void showError(String errString) {
Snackbar.make(rootView, errString, Snackbar.LENGTH_SHORT).show();
@Override
public void showLoader() {
btnEmail.setEnabled(false);
waitingView.setVisibility(View.VISIBLE);
}
@Override
public void hideLoader() {
btnEmail.setEnabled(true);
waitingView.setVisibility(View.GONE);
}
private void onRenderAuthProviders(List<RealmMeteorLoginServiceConfiguration> authProviders) {
@Override
public void showError(String message) {
Snackbar.make(rootView, message, Snackbar.LENGTH_SHORT).show();
}
@Override
public void showLoginServices(List<LoginServiceConfiguration> loginServiceList) {
HashMap<String, View> viewMap = new HashMap<>();
HashMap<String, Boolean> supportedMap = new HashMap<>();
for (OAuthProviderInfo info : OAuthProviderInfo.LIST) {
......@@ -82,7 +84,7 @@ public class LoginFragment extends AbstractServerConfigFragment {
supportedMap.put(info.serviceName, false);
}
for (RealmMeteorLoginServiceConfiguration authProvider : authProviders) {
for (LoginServiceConfiguration authProvider : loginServiceList) {
for (OAuthProviderInfo info : OAuthProviderInfo.LIST) {
if (!supportedMap.get(info.serviceName)
&& info.serviceName.equals(authProvider.getService())) {
......@@ -116,12 +118,12 @@ public class LoginFragment extends AbstractServerConfigFragment {
@Override
public void onResume() {
super.onResume();
authProvidersObserver.sub();
presenter.bindView(this);
}
@Override
public void onPause() {
authProvidersObserver.unsub();
presenter.release();
super.onPause();
}
}
package chat.rocket.android.fragment.server_config;
import android.support.annotation.NonNull;
import com.fernandocejas.arrow.optional.Optional;
import io.reactivex.android.schedulers.AndroidSchedulers;
import bolts.Task;
import chat.rocket.android.BackgroundLooper;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.shared.BasePresenter;
import chat.rocket.core.PublicSettingsConstants;
import chat.rocket.core.models.PublicSetting;
import chat.rocket.core.repositories.LoginServiceConfigurationRepository;
import chat.rocket.core.repositories.PublicSettingRepository;
public class LoginPresenter extends BasePresenter<LoginContract.View>
implements LoginContract.Presenter {
private final LoginServiceConfigurationRepository loginServiceConfigurationRepository;
private final PublicSettingRepository publicSettingRepository;
private final MethodCallHelper methodCallHelper;
public LoginPresenter(LoginServiceConfigurationRepository loginServiceConfigurationRepository,
PublicSettingRepository publicSettingRepository,
MethodCallHelper methodCallHelper) {
this.loginServiceConfigurationRepository = loginServiceConfigurationRepository;
this.publicSettingRepository = publicSettingRepository;
this.methodCallHelper = methodCallHelper;
}
@Override
public void bindView(@NonNull LoginContract.View view) {
super.bindView(view);
getLoginServices();
}
@Override
public void login(String username, String password) {
if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
return;
}
view.showLoader();
addSubscription(
publicSettingRepository.getById(PublicSettingsConstants.LDAP.ENABLE)
.subscribeOn(AndroidSchedulers.from(BackgroundLooper.get()))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(publicSettingOptional -> doLogin(username, password, publicSettingOptional))
);
}
private void getLoginServices() {
addSubscription(
loginServiceConfigurationRepository.getAll()
.subscribeOn(AndroidSchedulers.from(BackgroundLooper.get()))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
loginServiceConfigurations -> view.showLoginServices(loginServiceConfigurations))
);
}
private void doLogin(String username, String password, Optional<PublicSetting> optional) {
call(username, password, optional)
.continueWith(task -> {
if (task.isFaulted()) {
view.hideLoader();
view.showError(task.getError().getMessage());
}
return null;
});
}
private Task<Void> call(String username, String password, Optional<PublicSetting> optional) {
if (optional.isPresent() && optional.get().getValueAsBoolean()) {
return methodCallHelper.loginWithLdap(username, password);
}
return methodCallHelper.loginWithEmail(username, password);
}
}
package chat.rocket.android.fragment.server_config;
import chat.rocket.android.shared.BaseContract;
public interface RetryLoginContract {
interface View extends BaseContract.View {
void showRetry(String token);
void showError(String message);
void showLoader();
void hideLoader();
}
interface Presenter extends BaseContract.Presenter<View> {
void onLogin(String token);
}
}
......@@ -7,16 +7,20 @@ import android.widget.TextView;
import chat.rocket.android.R;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.persistence.realm.models.internal.RealmSession;
import chat.rocket.persistence.realm.RealmObjectObserver;
import chat.rocket.persistence.realm.RealmStore;
import chat.rocket.core.interactors.SessionInteractor;
import chat.rocket.persistence.realm.repositories.RealmSessionRepository;
/**
* Login screen.
*/
public class RetryLoginFragment extends AbstractServerConfigFragment {
private RealmObjectObserver<RealmSession> sessionObserver;
public class RetryLoginFragment extends AbstractServerConfigFragment
implements RetryLoginContract.View {
private RetryLoginContract.Presenter presenter;
private View btnRetry;
private View waitingView;
private TextView txtError;
@Override
protected int getLayout() {
......@@ -26,56 +30,52 @@ public class RetryLoginFragment extends AbstractServerConfigFragment {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sessionObserver = RealmStore.get(hostname)
.createObjectObserver(RealmSession::queryDefaultSession)
.setOnUpdateListener(this::onRenderServerConfigSession);
presenter = new RetryLoginPresenter(
new SessionInteractor(new RealmSessionRepository(hostname)),
new MethodCallHelper(getContext(), hostname)
);
}
@Override
protected void onSetupView() {
public void onResume() {
super.onResume();
presenter.bindView(this);
}
private void onRenderServerConfigSession(RealmSession session) {
if (session == null) {
return;
}
@Override
public void onPause() {
presenter.release();
super.onPause();
}
final String token = session.getToken();
if (!TextUtils.isEmpty(token)) {
final View btnRetry = rootView.findViewById(R.id.btn_retry_login);
final View waitingView = rootView.findViewById(R.id.waiting);
waitingView.setVisibility(View.GONE);
btnRetry.setOnClickListener(view -> {
view.setEnabled(false);
waitingView.setVisibility(View.VISIBLE);
@Override
protected void onSetupView() {
btnRetry = rootView.findViewById(R.id.btn_retry_login);
waitingView = rootView.findViewById(R.id.waiting);
txtError = (TextView) rootView.findViewById(R.id.txt_error_description);
}
new MethodCallHelper(getContext(), hostname).loginWithToken(token)
.continueWith(task -> {
if (task.isFaulted()) {
view.setEnabled(true);
waitingView.setVisibility(View.GONE);
}
return null;
});
});
}
@Override
public void showRetry(String token) {
waitingView.setVisibility(View.GONE);
btnRetry.setOnClickListener(view -> presenter.onLogin(token));
}
final String error = session.getError();
final TextView txtError = (TextView) rootView.findViewById(R.id.txt_error_description);
if (!TextUtils.isEmpty(error)) {
txtError.setText(error);
}
@Override
public void showError(String message) {
txtError.setText(message);
}
@Override
public void onResume() {
super.onResume();
sessionObserver.sub();
public void showLoader() {
btnRetry.setEnabled(false);
waitingView.setVisibility(View.VISIBLE);
}
@Override
public void onPause() {
sessionObserver.unsub();
super.onPause();
public void hideLoader() {
btnRetry.setEnabled(true);
waitingView.setVisibility(View.GONE);
}
}
package chat.rocket.android.fragment.server_config;
import android.support.annotation.NonNull;
import com.fernandocejas.arrow.optional.Optional;
import io.reactivex.android.schedulers.AndroidSchedulers;
import chat.rocket.android.BackgroundLooper;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.shared.BasePresenter;
import chat.rocket.core.interactors.SessionInteractor;
import chat.rocket.core.models.Session;
public class RetryLoginPresenter extends BasePresenter<RetryLoginContract.View>
implements RetryLoginContract.Presenter {
private final SessionInteractor sessionInteractor;
private final MethodCallHelper methodCallHelper;
public RetryLoginPresenter(SessionInteractor sessionInteractor,
MethodCallHelper methodCallHelper) {
this.sessionInteractor = sessionInteractor;
this.methodCallHelper = methodCallHelper;
}
@Override
public void bindView(@NonNull RetryLoginContract.View view) {
super.bindView(view);
subscribeToDefaultSession();
}
@Override
public void onLogin(String token) {
view.showLoader();
methodCallHelper.loginWithToken(token)
.continueWith(task -> {
if (task.isFaulted()) {
view.hideLoader();
}
return null;
});
}
private void subscribeToDefaultSession() {
addSubscription(
sessionInteractor.getDefault()
.subscribeOn(AndroidSchedulers.from(BackgroundLooper.get()))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::onSession)
);
}
private void onSession(Optional<Session> sessionOptional) {
if (!sessionOptional.isPresent()) {
return;
}
final Session session = sessionOptional.get();
final String token = session.getToken();
if (!TextUtils.isEmpty(token)) {
view.showRetry(token);
}
final String errorMessage = session.getError();
if (!TextUtils.isEmpty(errorMessage)) {
view.showError(errorMessage);
}
}
}
......@@ -15,13 +15,11 @@ public class GcmPushSettingHelper {
public static RealmResults<RealmPublicSetting> queryForGcmPushEnabled(Realm realm) {
return realm.where(RealmPublicSetting.class)
.equalTo(RealmPublicSetting.ID, PublicSettingsConstants.Push.ENABLE)
.or()
.equalTo(RealmPublicSetting.ID, PublicSettingsConstants.Push.GCM_PROJECT_NUMBER)
.findAll();
}
public static boolean isGcmPushEnabled(List<RealmPublicSetting> results) {
return isPushEnabled(results) && hasValidGcmConfig(results);
return isPushEnabled(results);
}
private static boolean isPushEnabled(List<RealmPublicSetting> results) {
......@@ -32,13 +30,4 @@ public class GcmPushSettingHelper {
}
return false;
}
private static boolean hasValidGcmConfig(List<RealmPublicSetting> results) {
for (RealmPublicSetting setting : results) {
if (PublicSettingsConstants.Push.GCM_PROJECT_NUMBER.equals(setting.getId())) {
return !TextUtils.isEmpty(setting.getValue());
}
}
return false;
}
}
......@@ -10,6 +10,7 @@ import io.realm.RealmResults;
import java.io.IOException;
import java.util.List;
import bolts.Task;
import chat.rocket.android.R;
import chat.rocket.android.RocketChatCache;
import chat.rocket.android.api.RaixPushHelper;
import chat.rocket.android.helper.LogIfError;
......@@ -66,10 +67,7 @@ public class GcmPushRegistrationObserver extends AbstractModelObserver<GcmPushRe
}
private Task<Void> registerGcmTokenForServer() throws IOException {
final String senderId = RealmPublicSetting
.getString(realmHelper, PublicSettingsConstants.Push.GCM_PROJECT_NUMBER, "").trim();
final String gcmToken = getGcmToken(senderId);
final String gcmToken = getGcmToken(getSenderId());
final RealmUser currentUser = realmHelper.executeTransactionForRead(realm ->
RealmUser.queryCurrentUser(realm).findFirst());
final String userId = currentUser != null ? currentUser.getId() : null;
......@@ -84,4 +82,15 @@ public class GcmPushRegistrationObserver extends AbstractModelObserver<GcmPushRe
.getToken(senderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
}
private String getSenderId() {
final String senderId = RealmPublicSetting
.getString(realmHelper, PublicSettingsConstants.Push.GCM_PROJECT_NUMBER, "").trim();
if (senderId.length() != 0) {
return senderId;
}
return context.getString(R.string.gcm_sender_id);
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="gcm_sender_id">YOUR-SENDER-ID</string>
</resources>
\ No newline at end of file
......@@ -3,6 +3,8 @@ package chat.rocket.persistence.realm.models.ddp;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import chat.rocket.core.models.LoginServiceConfiguration;
/**
* subscription model for "meteor_accounts_loginServiceConfiguration".
*/
......@@ -19,9 +21,9 @@ public class RealmMeteorLoginServiceConfiguration
@PrimaryKey private String _id;
private String service;
private String consumerKey; //for Twitter
private String appId; //for Facebook
private String clientId; //for other auth providers
private String consumerKey; // for Twitter
private String appId; // for Facebook
private String clientId; // for other auth providers
public String getId() {
return _id;
......@@ -62,4 +64,24 @@ public class RealmMeteorLoginServiceConfiguration
public void setClientId(String clientId) {
this.clientId = clientId;
}
public LoginServiceConfiguration asLoginServiceConfiguration() {
return LoginServiceConfiguration.builder()
.setId(_id)
.setService(service)
.setKey(getServiceKey())
.build();
}
private String getServiceKey() {
if (consumerKey != null) {
return consumerKey;
}
if (appId != null) {
return appId;
}
return clientId;
}
}
......@@ -7,6 +7,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import chat.rocket.core.JsonConstants;
import chat.rocket.core.models.PublicSetting;
import chat.rocket.persistence.realm.RealmHelper;
/**
......@@ -113,4 +114,14 @@ public class RealmPublicSetting extends RealmObject {
public void setMeta(String meta) {
this.meta = meta;
}
public PublicSetting asPublicSetting() {
return PublicSetting.builder()
.setId(_id)
.setGroup(group)
.setType(type)
.setValue(value)
.setUpdatedAt(_updatedAt)
.build();
}
}
package chat.rocket.persistence.realm.repositories;
import android.os.Looper;
import android.support.v4.util.Pair;
import com.fernandocejas.arrow.optional.Optional;
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.realm.RealmResults;
import java.util.ArrayList;
import java.util.List;
import chat.rocket.core.models.LoginServiceConfiguration;
import chat.rocket.core.repositories.LoginServiceConfigurationRepository;
import chat.rocket.persistence.realm.RealmStore;
import chat.rocket.persistence.realm.models.ddp.RealmMeteorLoginServiceConfiguration;
import hu.akarnokd.rxjava.interop.RxJavaInterop;
public class RealmLoginServiceConfigurationRepository extends RealmRepository
implements LoginServiceConfigurationRepository {
private final String hostname;
public RealmLoginServiceConfigurationRepository(String hostname) {
this.hostname = hostname;
}
@Override
public Single<Optional<LoginServiceConfiguration>> getByName(String serviceName) {
return Single.defer(() -> Flowable.using(
() -> new Pair<>(RealmStore.getRealm(hostname), Looper.myLooper()),
pair -> RxJavaInterop.toV2Flowable(
pair.first.where(RealmMeteorLoginServiceConfiguration.class)
.equalTo(RealmMeteorLoginServiceConfiguration.SERVICE, serviceName)
.findAll()
.<RealmResults<RealmMeteorLoginServiceConfiguration>>asObservable()),
pair -> close(pair.first, pair.second)
)
.unsubscribeOn(AndroidSchedulers.from(Looper.myLooper()))
.filter(it -> it.isLoaded() && it.isValid() && it.size() > 0)
.map(it -> Optional.of(it.get(0).asLoginServiceConfiguration()))
.first(Optional.absent()));
}
@Override
public Flowable<List<LoginServiceConfiguration>> getAll() {
return Flowable.defer(() -> Flowable.using(
() -> new Pair<>(RealmStore.getRealm(hostname), Looper.myLooper()),
pair -> RxJavaInterop
.toV2Flowable(pair.first.where(RealmMeteorLoginServiceConfiguration.class)
.findAll()
.asObservable()),
pair -> close(pair.first, pair.second)
)
.unsubscribeOn(AndroidSchedulers.from(Looper.myLooper()))
.filter(it -> it.isLoaded() && it.isValid())
.map(this::toList));
}
private List<LoginServiceConfiguration> toList(
RealmResults<RealmMeteorLoginServiceConfiguration> realmConfigurations) {
final int total = realmConfigurations.size();
final List<LoginServiceConfiguration> serviceConfigurations = new ArrayList<>(total);
for (int i = 0; i < total; i++) {
serviceConfigurations.add(realmConfigurations.get(i).asLoginServiceConfiguration());
}
return serviceConfigurations;
}
}
package chat.rocket.persistence.realm.repositories;
import android.os.Looper;
import android.support.v4.util.Pair;
import com.fernandocejas.arrow.optional.Optional;
import io.reactivex.Flowable;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.realm.RealmResults;
import chat.rocket.core.models.PublicSetting;
import chat.rocket.core.repositories.PublicSettingRepository;
import chat.rocket.persistence.realm.RealmStore;
import chat.rocket.persistence.realm.models.ddp.RealmPublicSetting;
import hu.akarnokd.rxjava.interop.RxJavaInterop;
public class RealmPublicSettingRepository extends RealmRepository
implements PublicSettingRepository {
private final String hostname;
public RealmPublicSettingRepository(String hostname) {
this.hostname = hostname;
}
@Override
public Single<Optional<PublicSetting>> getById(String id) {
return Single.defer(() -> Flowable.using(
() -> new Pair<>(RealmStore.getRealm(hostname), Looper.myLooper()),
pair -> RxJavaInterop.toV2Flowable(
pair.first.where(RealmPublicSetting.class)
.equalTo(RealmPublicSetting.ID, id)
.findAll()
.<RealmResults<RealmPublicSetting>>asObservable()),
pair -> close(pair.first, pair.second)
)
.unsubscribeOn(AndroidSchedulers.from(Looper.myLooper()))
.filter(it -> it.isLoaded() && it.isValid() && it.size() > 0)
.map(it -> Optional.of(it.get(0).asPublicSetting()))
.first(Optional.absent()));
}
}
package chat.rocket.core.models;
import com.google.auto.value.AutoValue;
@AutoValue
public abstract class LoginServiceConfiguration {
public abstract String getId();
public abstract String getService();
public abstract String getKey();
public static Builder builder() {
return new AutoValue_LoginServiceConfiguration.Builder();
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setId(String id);
public abstract Builder setService(String service);
public abstract Builder setKey(String key);
public abstract LoginServiceConfiguration build();
}
}
package chat.rocket.core.models;
import com.google.auto.value.AutoValue;
import javax.annotation.Nullable;
@AutoValue
public abstract class PublicSetting {
public abstract String getId();
@Nullable
public abstract String getGroup();
@Nullable
public abstract String getType();
public abstract String getValue();
public abstract long getUpdatedAt();
public boolean getValueAsBoolean() {
return Boolean.parseBoolean(getValue());
}
public static Builder builder() {
return new AutoValue_PublicSetting.Builder();
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setId(String id);
public abstract Builder setGroup(String group);
public abstract Builder setType(String type);
public abstract Builder setValue(String value);
public abstract Builder setUpdatedAt(long updatedAt);
public abstract PublicSetting build();
}
}
package chat.rocket.core.repositories;
import com.fernandocejas.arrow.optional.Optional;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.List;
import chat.rocket.core.models.LoginServiceConfiguration;
public interface LoginServiceConfigurationRepository {
Single<Optional<LoginServiceConfiguration>> getByName(String serviceName);
Flowable<List<LoginServiceConfiguration>> getAll();
}
package chat.rocket.core.repositories;
import com.fernandocejas.arrow.optional.Optional;
import io.reactivex.Single;
import chat.rocket.core.models.PublicSetting;
public interface PublicSettingRepository {
Single<Optional<PublicSetting>> getById(String id);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment