/* * The contents of this file are subject to the OpenMRS Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.mobile.activities.login; import org.openmrs.mobile.R; import org.openmrs.mobile.activities.BasePresenter; import org.openmrs.mobile.api.RestApi; import org.openmrs.mobile.api.RestServiceBuilder; import org.openmrs.mobile.api.UserService; import org.openmrs.mobile.api.retrofit.VisitApi; import org.openmrs.mobile.application.OpenMRS; import org.openmrs.mobile.application.OpenMRSLogger; import org.openmrs.mobile.dao.LocationDAO; import org.openmrs.mobile.databases.OpenMRSSQLiteOpenHelper; import org.openmrs.mobile.listeners.retrofit.GetVisitTypeCallbackListener; import org.openmrs.mobile.models.Location; import org.openmrs.mobile.models.Results; import org.openmrs.mobile.models.Session; import org.openmrs.mobile.models.VisitType; import org.openmrs.mobile.net.AuthorizationManager; import org.openmrs.mobile.utilities.ApplicationConstants; import org.openmrs.mobile.utilities.NetworkUtils; import org.openmrs.mobile.utilities.StringUtils; import org.openmrs.mobile.utilities.ToastUtil; import java.util.ArrayList; import java.util.List; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; public class LoginPresenter extends BasePresenter implements LoginContract.Presenter { private RestApi restApi; private VisitApi visitApi; private UserService userService; private LoginContract.View loginView; private OpenMRS mOpenMRS; private OpenMRSLogger mLogger; private AuthorizationManager authorizationManager; private LocationDAO locationDAO; private boolean mWipeRequired; public LoginPresenter(LoginContract.View loginView, OpenMRS openMRS) { this.loginView = loginView; this.mOpenMRS = openMRS; this.mLogger = openMRS.getOpenMRSLogger(); this.loginView.setPresenter(this); this.authorizationManager = new AuthorizationManager(); this.locationDAO = new LocationDAO(); this.restApi = RestServiceBuilder.createService(RestApi.class); this.visitApi = new VisitApi(); this.userService = new UserService(); } public LoginPresenter(RestApi restApi, VisitApi visitApi, LocationDAO locationDAO, UserService userService, LoginContract.View loginView, OpenMRS mOpenMRS, OpenMRSLogger mLogger, AuthorizationManager authorizationManager) { this.restApi = restApi; this.visitApi = visitApi; this.locationDAO = locationDAO; this.userService = userService; this.loginView = loginView; this.mOpenMRS = mOpenMRS; this.mLogger = mLogger; this.authorizationManager = authorizationManager; this.loginView.setPresenter(this); } @Override public void subscribe() { // This method is intentionally empty } @Override public void login(String username, String password, String url, String oldUrl) { if (validateLoginFields(username, password, url)) { loginView.hideSoftKeys(); if ((!mOpenMRS.getUsername().equals(ApplicationConstants.EMPTY_STRING) && !mOpenMRS.getUsername().equals(username)) || ((!mOpenMRS.getServerUrl().equals(ApplicationConstants.EMPTY_STRING) && !mOpenMRS.getServerUrl().equals(oldUrl))) || mWipeRequired) { loginView.showWarningDialog(); } else { authenticateUser(username, password, url); } } } @Override public void authenticateUser(final String username, final String password, final String url) { authenticateUser(username, password, url, mWipeRequired); } @Override public void authenticateUser(final String username, final String password, final String url, final boolean wipeDatabase) { loginView.showLoadingAnimation(); if (NetworkUtils.isOnline()) { mWipeRequired = wipeDatabase; RestApi restApi = RestServiceBuilder.createService(RestApi.class, username, password); Call<Session> call = restApi.getSession(); call.enqueue(new Callback<Session>() { @Override public void onResponse(Call<Session> call, Response<Session> response) { if (response.isSuccessful()) { mLogger.d(response.body().toString()); Session session = response.body(); if (session.isAuthenticated()) { if (wipeDatabase) { mOpenMRS.deleteDatabase(OpenMRSSQLiteOpenHelper.DATABASE_NAME); setData(session.getSessionId(), url, username, password); mWipeRequired = false; } if (authorizationManager.isUserNameOrServerEmpty()) { setData(session.getSessionId(), url, username, password); } else { mOpenMRS.setSessionToken(session.getSessionId()); } visitApi.getVisitType(new GetVisitTypeCallbackListener() { @Override public void onGetVisitTypeResponse(VisitType visitType) { OpenMRS.getInstance().setVisitTypeUUID(visitType.getUuid()); } @Override public void onResponse() { // This method is intentionally empty } @Override public void onErrorResponse(String errorMessage) { loginView.showToast("Failed to fetch visit type", ToastUtil.ToastType.ERROR); } }); setLogin(true, url); userService.updateUserInformation(username); loginView.userAuthenticated(); loginView.finishLoginActivity(); } else { loginView.hideLoadingAnimation(); loginView.showInvalidLoginOrPasswordSnackbar(); } } else { loginView.hideLoadingAnimation(); loginView.showToast(response.message(), ToastUtil.ToastType.ERROR); } } @Override public void onFailure(Call<Session> call, Throwable t) { loginView.hideLoadingAnimation(); loginView.showToast(t.getMessage(), ToastUtil.ToastType.ERROR); } }); } else { if (mOpenMRS.isUserLoggedOnline() && url.equals(mOpenMRS.getLastLoginServerUrl())) { if (mOpenMRS.getUsername().equals(username) && mOpenMRS.getPassword().equals(password)) { mOpenMRS.setSessionToken(mOpenMRS.getLastSessionToken()); loginView.showToast("LoggedIn in offline mode.", ToastUtil.ToastType.NOTICE); loginView.userAuthenticated(); loginView.finishLoginActivity(); } else { loginView.hideLoadingAnimation(); loginView.showToast(R.string.auth_failed_dialog_message, ToastUtil.ToastType.ERROR); } } else if (NetworkUtils.hasNetwork()) { loginView.showToast(R.string.offline_mode_unsupported_in_first_login, ToastUtil.ToastType.ERROR); loginView.hideLoadingAnimation(); } else { loginView.showToast(R.string.no_internet_conn_dialog_message, ToastUtil.ToastType.ERROR); loginView.hideLoadingAnimation(); } } } @Override public void saveLocationsToDatabase(List<Location> locationList, String selectedLocation) { mOpenMRS.setLocation(selectedLocation); locationDAO.deleteAllLocations(); for (int i = 0; i < locationList.size(); i++) { locationDAO.saveLocation(locationList.get(i)) .observeOn(Schedulers.io()) .subscribe(); } } @Override public void loadLocations(final String url) { loginView.showLocationLoadingAnimation(); if (NetworkUtils.hasNetwork()) { String locationEndPoint = url + ApplicationConstants.API.REST_ENDPOINT + "location"; Call<Results<Location>> call = restApi.getLocations(locationEndPoint, "Login Location", "full"); call.enqueue(new Callback<Results<Location>>() { @Override public void onResponse(Call<Results<Location>> call, Response<Results<Location>> response) { if (response.isSuccessful()) { RestServiceBuilder.changeBaseUrl(url.trim()); mOpenMRS.setServerUrl(url); loginView.initLoginForm(response.body().getResults(), url); loginView.startFormListService(); loginView.setLocationErrorOccurred(false); } else { loginView.showInvalidURLSnackbar("Failed to fetch server's locations"); loginView.setLocationErrorOccurred(true); loginView.initLoginForm(new ArrayList<Location>(), url); } loginView.hideUrlLoadingAnimation(); } @Override public void onFailure(Call<Results<Location>> call, Throwable t) { loginView.hideUrlLoadingAnimation(); loginView.showInvalidURLSnackbar(t.getMessage()); loginView.initLoginForm(new ArrayList<Location>(), url); loginView.setLocationErrorOccurred(true); } }); } else { addSubscription(locationDAO.getLocations() .observeOn(AndroidSchedulers.mainThread()) .subscribe(locations -> { if (locations.size() > 0) { loginView.initLoginForm(locations, url); loginView.setLocationErrorOccurred(false); } else { loginView.showToast("Network not available.", ToastUtil.ToastType.ERROR); loginView.setLocationErrorOccurred(true); } loginView.hideLoadingAnimation(); })); } } private boolean validateLoginFields(String username, String password, String url) { return StringUtils.notEmpty(username) || StringUtils.notEmpty(password) || StringUtils.notEmpty(url); } private void setData(String sessionToken,String url, String username, String password) { mOpenMRS.setSessionToken(sessionToken); mOpenMRS.setServerUrl(url); mOpenMRS.setUsername(username); mOpenMRS.setPassword(password); } private void setLogin(boolean isLogin, String serverUrl) { mOpenMRS.setUserLoggedOnline(isLogin); mOpenMRS.setLastLoginServerUrl(serverUrl); } }