Skip to content

Commit

Permalink
Merge pull request #782 from opensrp/brac-hnpp-x
Browse files Browse the repository at this point in the history
Store role to use from app side
  • Loading branch information
mahmud6390 authored May 6, 2021
2 parents 41f3572 + 63adabf commit 494376a
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Run unit tests with Gradle
run: ./gradlew opensrp-app:clean opensrp-app:jacocoTestReport --info
run: ./gradlew opensrp-app:clean opensrp-app:jacocoTestReport --stacktrace
- name: Generate Javadoc with Gradle
run: ./gradlew javadoc
- name: Upload coverage to Coveralls with Gradle
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ subprojects {
ext.androidToolsBuildGradle = '4.0.0'
ext.androidBuildToolsVersion = '29.0.3'
ext.androidMinSdkVersion = 18
ext.androidCompileSdkVersion = 28
ext.androidTargetSdkVersion = 28
ext.androidCompileSdkVersion = 29
ext.androidTargetSdkVersion = 29

ext.androidAnnotationsVersion = '3.0.1'
ext.androidAnnotationsAPIVersion = '3.0.1'
Expand Down
1 change: 1 addition & 0 deletions opensrp-app/res/layout/base_register_search_bar.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
android:layout_alignParentTop="true"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:foregroundTint="@color/white"
android:drawableLeft="@drawable/ic_icon_filter"
android:drawablePadding="@dimen/register_search_bar_min_margin"
android:drawableStart="@drawable/ic_icon_filter"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ public class AllConstants {

public static final String CLIENT_FORM_ASSET_VERSION = "base version";
public static final String RETURN_COUNT = "return_count";
public static final String LIMIT = "limit";
public static final String COMBINE_CHECKBOX_OPTION_VALUES = "combine_checkbox_option_values";

public static final String GPS = "gps";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public static final class INTENT_KEY {
public final static String ACCOUNT_REFRESH_TOKEN = "ACCOUNT_REFRESH_TOKEN";
public final static String ACCOUNT_LOCAL_PASSWORD_SALT = "ACCOUNT_LOCAL_PASSWORD_SALT";
public final static String ACCOUNT_LOCAL_PASSWORD = "ACCOUNT_LOCAL_PASSWORD";
public final static String ACCOUNT_ROLES = "ACCOUNT_ROLES";
}

public static final class TOKEN_TYPE {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.smartregister.view.contract.BaseLoginContract;

import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;

import timber.log.Timber;
Expand Down Expand Up @@ -117,7 +118,7 @@ protected LoginResponse doInBackground(Void... params) {
mAccountManager.setUserData(account, AccountHelper.INTENT_KEY.ACCOUNT_LOCAL_PASSWORD_SALT, userData.getString(AccountHelper.INTENT_KEY.ACCOUNT_LOCAL_PASSWORD_SALT));
mAccountManager.setUserData(account, AccountHelper.INTENT_KEY.ACCOUNT_NAME, userData.getString(AccountHelper.INTENT_KEY.ACCOUNT_NAME));
mAccountManager.setUserData(account, AccountHelper.INTENT_KEY.ACCOUNT_REFRESH_TOKEN, response.getRefreshToken());

mAccountManager.setUserData(account, AccountHelper.INTENT_KEY.ACCOUNT_ROLES, user.getRoles() != null ? user.getRoles().toString() : Collections.EMPTY_LIST.toString());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mAccountManager.notifyAccountAuthenticated(account);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ private byte[] getDecryptedAccountValue(String userName, KeyStore.PrivateKeyEntr
return null;
}

public List<String> getUserRoles(String userName){
String roles = AccountHelper.getAccountManagerValue(AccountHelper.INTENT_KEY.ACCOUNT_ROLES, userName, CoreLibrary.getInstance().getAccountAuthenticatorXml().getAccountType());
return Arrays.asList(roles);
}

public byte[] getDecryptedPassphraseValue(String userName) {
if (keyStore != null && userName != null) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@
import android.app.IntentService;
import android.content.Intent;

import org.json.JSONException;
import org.json.JSONObject;
import org.smartregister.AllConstants;
import org.smartregister.CoreLibrary;
import org.smartregister.service.HTTPAgent;

import java.util.LinkedHashMap;
import java.util.Map;

import timber.log.Timber;

/**
* Created by Vincent Karuri on 26/08/2019
*/
Expand All @@ -17,9 +25,87 @@ public BaseSyncIntentService(String name) {

@Override
protected void onHandleIntent(Intent intent) {
CoreLibrary coreLibrary = CoreLibrary.getInstance();
CoreLibrary coreLibrary = CoreLibrary.getInstance();
HTTPAgent httpAgent = coreLibrary.context().httpAgent();
httpAgent.setConnectTimeout(coreLibrary.getSyncConfiguration().getConnectTimeout());
httpAgent.setReadTimeout(coreLibrary.getSyncConfiguration().getReadTimeout());
}

/**
* A helper class for building the url request for intent services
*/
public static class RequestParamsBuilder {

private final Map<String, Object> paramMap;
private final StringBuilder getSyncParamsBuilder;
private final JSONObject postSyncParamsBuilder;

public RequestParamsBuilder() {
this.paramMap = new LinkedHashMap<>();
this.getSyncParamsBuilder = new StringBuilder();
this.postSyncParamsBuilder = new JSONObject();
}

public RequestParamsBuilder addServerVersion(long value) {
paramMap.put(AllConstants.SERVER_VERSION, value);
return this;
}

public RequestParamsBuilder addEventPullLimit(int value) {
paramMap.put(AllConstants.LIMIT, value);
return this;
}

public RequestParamsBuilder configureSyncFilter(String syncFilterParam, String syncFilterValue) {
paramMap.put(syncFilterParam, syncFilterValue);
return this;
}

public RequestParamsBuilder returnCount(boolean value) {
paramMap.put(AllConstants.RETURN_COUNT, value);
return this;
}

public RequestParamsBuilder addParam(String key, Object value) {
paramMap.put(key, value);
return this;
}

public RequestParamsBuilder removeParam(String key) {
paramMap.remove(key);
return this;
}

public String build() {

for (Map.Entry<String, Object> entry : paramMap.entrySet()) {

if (CoreLibrary.getInstance().getSyncConfiguration().isSyncUsingPost()) {

try {
postSyncParamsBuilder.put(entry.getKey(), entry.getValue());
} catch (JSONException e) {
Timber.e(e);
}

} else {

if (0 != getSyncParamsBuilder.length()) {
getSyncParamsBuilder.append('&');
}

getSyncParamsBuilder.append(entry.getKey()).append('=').append(entry.getValue());
}

}

return CoreLibrary.getInstance().getSyncConfiguration().isSyncUsingPost() ? postSyncParamsBuilder.toString() : getSyncParamsBuilder.toString();
}

@Override
public String toString() {
return build();
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public class SyncIntentService extends BaseSyncIntentService {
protected ValidateAssignmentHelper validateAssignmentHelper;
private long totalRecords;
private int fetchedRecords = 0;
//this variable using to track the sync request goes along with add events/clients
private boolean isEmptyToAdd = true;

public SyncIntentService() {
super("SyncIntentService");
Expand Down Expand Up @@ -165,21 +167,15 @@ private synchronized void fetchRetry(final int count, boolean returnCount) {

startEventTrace(FETCH, 0);

String url = baseUrl + SYNC_URL;
Response resp;
if (configs.isSyncUsingPost()) {
JSONObject syncParams = new JSONObject();
syncParams.put(configs.getSyncFilterParam().value(), configs.getSyncFilterValue());
syncParams.put("serverVersion", lastSyncDatetime);
syncParams.put("limit", getEventPullLimit());
syncParams.put(AllConstants.RETURN_COUNT, returnCount);
resp = httpAgent.postWithJsonResponse(url, syncParams.toString());
} else {
url += "?" + configs.getSyncFilterParam().value() + "=" + configs.getSyncFilterValue() + "&serverVersion=" + lastSyncDatetime + "&limit=" + getEventPullLimit();
Timber.i("URL: %s", url);
resp = httpAgent.fetch(url);
}
BaseSyncIntentService.RequestParamsBuilder syncParamBuilder = new BaseSyncIntentService.RequestParamsBuilder().
configureSyncFilter(configs.getSyncFilterParam().value(), configs.getSyncFilterValue()).addServerVersion(lastSyncDatetime).addEventPullLimit(getEventPullLimit());

Response resp = getUrlResponse(baseUrl + SYNC_URL, syncParamBuilder, configs, returnCount);
if (resp == null) {
FetchStatus.fetchedFailed.setDisplayValue("Empty response");
complete(FetchStatus.fetchedFailed);
return;
}
if (resp.isUrlError()) {
FetchStatus.fetchedFailed.setDisplayValue(resp.status().displayValue());
complete(FetchStatus.fetchedFailed);
Expand Down Expand Up @@ -209,6 +205,32 @@ private synchronized void fetchRetry(final int count, boolean returnCount) {
}
}

/**
* This methods makes a request to the server using either Get or Post as is configured by {@link org.smartregister.SyncConfiguration#isSyncUsingPost()}
*
* @param baseURL the base url for the request
* @param requestParamsBuilder the query string builder object
* @param configs the Sync Configuration object with various configurations
* @param returnCount a boolean flag, whether to return the total count of records as part of the response (field - total_records)
*/
protected Response getUrlResponse(@NonNull String baseURL, @NonNull BaseSyncIntentService.RequestParamsBuilder requestParamsBuilder, @NonNull SyncConfiguration configs, boolean returnCount) {
Response response;
String requestUrl = baseURL;

if (configs.isSyncUsingPost()) {

response = httpAgent.postWithJsonResponse(requestUrl, requestParamsBuilder.returnCount(returnCount).build());

} else {
requestUrl += "?" + requestParamsBuilder.build();
Timber.i("URL: %s", requestUrl);
response = httpAgent.fetch(requestUrl);
}

return response;

}

private void processFetchedEvents(Response resp, ECSyncHelper ecSyncUpdater, final int count) throws JSONException {
int eCount;
JSONObject jsonObject = new JSONObject();
Expand Down Expand Up @@ -278,7 +300,7 @@ private boolean pushToServer() {

private boolean pushECToServer(EventClientRepository db) {
boolean isSuccessfulPushSync = true;

isEmptyToAdd = true;
// push foreign events to server
int totalEventCount = db.getUnSyncedEventsCount();
int eventsUploadedCount = 0;
Expand Down Expand Up @@ -312,6 +334,7 @@ private boolean pushECToServer(EventClientRepository db) {
} catch (JSONException e) {
Timber.e(e);
}
isEmptyToAdd = false;
String jsonPayload = request.toString();
startEventTrace(PUSH, eventsUploadedCount);
Response<String> response = httpAgent.post(
Expand Down Expand Up @@ -345,6 +368,10 @@ private void startEventTrace(String action, int count) {
}
}

public boolean isEmptyToAdd() {
return isEmptyToAdd;
}

private void sendSyncStatusBroadcastMessage(FetchStatus fetchStatus) {
Intent intent = new Intent();
intent.setAction(SyncStatusBroadcastReceiver.ACTION_SYNC_STATUS);
Expand All @@ -359,7 +386,7 @@ protected void complete(FetchStatus fetchStatus) {
intent.putExtra(SyncStatusBroadcastReceiver.EXTRA_COMPLETE_STATUS, true);

sendBroadcast(intent);

//sync time not update if sync is fail
if (!fetchStatus.equals(FetchStatus.noConnection) && !fetchStatus.equals(FetchStatus.fetchedFailed)) {
ECSyncHelper ecSyncUpdater = ECSyncHelper.getInstance(context);
Expand All @@ -379,7 +406,6 @@ protected void updateProgress(@IntRange(from = 0) int progress, @IntRange(from =

protected Pair<Long, Long> getMinMaxServerVersions(JSONObject jsonObject) {
final String EVENTS = "events";
final String SERVER_VERSION = "serverVersion";
try {
if (jsonObject != null && jsonObject.has(EVENTS)) {
JSONArray events = jsonObject.getJSONArray(EVENTS);
Expand All @@ -391,8 +417,8 @@ protected Pair<Long, Long> getMinMaxServerVersions(JSONObject jsonObject) {
Object o = events.get(i);
if (o instanceof JSONObject) {
JSONObject jo = (JSONObject) o;
if (jo.has(SERVER_VERSION)) {
long serverVersion = jo.getLong(SERVER_VERSION);
if (jo.has(AllConstants.SERVER_VERSION)) {
long serverVersion = jo.getLong(AllConstants.SERVER_VERSION);
if (serverVersion > maxServerVersion) {
maxServerVersion = serverVersion;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public void setUp() {
when(view.getActivityContext()).thenReturn(activity);

loginResponseData = new LoginResponseData();
loginResponseData.user = new User().withUsername(username);
loginResponseData.user = new User().withUsername(username).withRole("READ_ROLE").withRole("WRITE_ROLE").withRole("PROVIDER_ROLE");
loginResponseData.time = new Time(new Date(), TimeZone.getTimeZone("Africa/Nairobi"));

when(context.getHttpAgent()).thenReturn(httpAgent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
Expand Down Expand Up @@ -40,6 +41,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
Expand All @@ -59,7 +61,7 @@ public class SyncIntentServiceTest extends BaseRobolectricUnitTest {
private SyncConfiguration syncConfiguration;

@Captor
private ArgumentCaptor<Intent> intentArgumentCaptor;
private ArgumentCaptor<Intent> intentArgumentCaptor;

@Captor
private ArgumentCaptor<String> stringArgumentCaptor;
Expand Down Expand Up @@ -438,7 +440,7 @@ public void testPushECToServer() throws Exception {
Whitebox.invokeMethod(syncIntentService, "pushECToServer", eventClientRepository);

verify(eventClientRepository).markEventsAsSynced(pendingEvents);
verify(syncIntentService).updateProgress(1,2);
verify(syncIntentService).updateProgress(1, 2);

String syncUrl = stringArgumentCaptor.getAllValues().get(0);
assertEquals("https://sample-stage.smartregister.org/opensrp/rest/event/add", syncUrl);
Expand Down Expand Up @@ -483,6 +485,45 @@ public void testUpdateProgress() {
assertEquals("Sync upload progress 70%", actualFetchStatus.displayValue());
}

@Test
public void testGetUrlResponseCreatesValidUrlWithExtraParamsUsingGET() {

initMocksForPullECFromServerUsingPOST();
when(syncConfiguration.isSyncUsingPost()).thenReturn(false);
ResponseStatus responseStatus = ResponseStatus.failure;
responseStatus.setDisplayValue(ResponseErrorStatus.malformed_url.name());
Mockito.doReturn(new Response<>(responseStatus, null))
.when(httpAgent).fetch(stringArgumentCaptor.capture());
String removeParamKey = "some-other-param-to-remove";
BaseSyncIntentService.RequestParamsBuilder builder = new BaseSyncIntentService.RequestParamsBuilder().configureSyncFilter("locationId", "location-1")
.addServerVersion(0).addEventPullLimit(250).addParam("region", "au-west").addParam("is_enabled", true).addParam("some-other-param", 85l)
.addParam(removeParamKey, 745).removeParam(removeParamKey);
syncIntentService.getUrlResponse("https://sample-stage.smartregister.org/opensrp/rest/event/sync", builder, syncConfiguration, false);

String syncUrl = stringArgumentCaptor.getValue();
assertEquals("https://sample-stage.smartregister.org/opensrp/rest/event/sync?locationId=location-1&serverVersion=0&limit=250&region=au-west&is_enabled=true&some-other-param=85", syncUrl);
assertTrue(syncIntentService.isEmptyToAdd());
}

@Test
public void testGetUrlResponseCreatesValidUrlWithExtraParamsUsingPost() {
syncIntentService = spy(syncIntentService);

initMocksForPullECFromServerUsingPOST();
ResponseStatus responseStatus = ResponseStatus.failure;
responseStatus.setDisplayValue(ResponseErrorStatus.malformed_url.name());
Mockito.doReturn(new Response<>(responseStatus, null))
.when(httpAgent).postWithJsonResponse(ArgumentMatchers.anyString(), stringArgumentCaptor.capture());

BaseSyncIntentService.RequestParamsBuilder builder = new BaseSyncIntentService.RequestParamsBuilder().configureSyncFilter("locationId", "location-2")
.addServerVersion(0).addEventPullLimit(500).addParam("region", "au-east").addParam("is_enabled", false).addParam("some-other-param", 36);
syncIntentService.getUrlResponse("https://sample-stage.smartregister.org/opensrp/rest/event/sync", builder, syncConfiguration, true);

String requestString = stringArgumentCaptor.getValue();
assertEquals("{\"locationId\":\"location-2\",\"serverVersion\":0,\"limit\":500,\"region\":\"au-east\",\"is_enabled\":false,\"some-other-param\":36,\"return_count\":true}", requestString);

}

private void initMocksForPullECFromServerUsingPOST() {
Whitebox.setInternalState(syncIntentService, "httpAgent", httpAgent);
when(syncConfiguration.isSyncUsingPost()).thenReturn(true);
Expand Down

0 comments on commit 494376a

Please sign in to comment.