From 983693f79d3b86399a6aa2736c9f6b797de81c32 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 30 Apr 2020 15:09:27 +0200 Subject: [PATCH 01/10] [ANDROSDK-1133] Upload single event notes --- .../core/event/internal/EventPostCall.java | 47 +++++++++++++++---- .../TrackedEntityInstancePostCall.java | 5 +- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventPostCall.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventPostCall.java index f9f2e3af34..b05f4c0384 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventPostCall.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventPostCall.java @@ -28,14 +28,22 @@ package org.hisp.dhis.android.core.event.internal; +import androidx.annotation.NonNull; + import org.hisp.dhis.android.core.arch.api.executors.internal.APICallExecutor; import org.hisp.dhis.android.core.arch.call.D2Progress; import org.hisp.dhis.android.core.arch.call.internal.D2ProgressManager; +import org.hisp.dhis.android.core.arch.db.querybuilders.internal.WhereClauseBuilder; +import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; import org.hisp.dhis.android.core.arch.helpers.UidsHelper; +import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; +import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.event.Event; import org.hisp.dhis.android.core.imports.TrackerImportConflict; import org.hisp.dhis.android.core.imports.internal.EventWebResponse; +import org.hisp.dhis.android.core.note.Note; +import org.hisp.dhis.android.core.note.NoteTableInfo; import org.hisp.dhis.android.core.systeminfo.DHISVersionManager; import org.hisp.dhis.android.core.systeminfo.SystemInfo; import org.hisp.dhis.android.core.systeminfo.internal.SystemInfoModuleDownloader; @@ -49,7 +57,6 @@ import javax.inject.Inject; -import androidx.annotation.NonNull; import dagger.Reusable; import io.reactivex.Observable; @@ -62,6 +69,7 @@ public final class EventPostCall { // adapter and stores private final EventStore eventStore; private final TrackedEntityDataValueStore trackedEntityDataValueStore; + private final IdentifiableObjectStore noteStore; private final EventImportHandler eventImportHandler; private final APICallExecutor apiCallExecutor; @@ -72,6 +80,7 @@ public final class EventPostCall { @NonNull EventService eventService, @NonNull EventStore eventStore, @NonNull TrackedEntityDataValueStore trackedEntityDataValueStore, + @NonNull IdentifiableObjectStore noteStore, @NonNull APICallExecutor apiCallExecutor, @NonNull EventImportHandler eventImportHandler, @NonNull SystemInfoModuleDownloader systemInfoDownloader) { @@ -79,6 +88,7 @@ public final class EventPostCall { this.eventService = eventService; this.eventStore = eventStore; this.trackedEntityDataValueStore = trackedEntityDataValueStore; + this.noteStore = noteStore; this.apiCallExecutor = apiCallExecutor; this.eventImportHandler = eventImportHandler; this.systemInfoDownloader = systemInfoDownloader; @@ -120,18 +130,20 @@ List queryDataToSync(List filteredEvents) { trackedEntityDataValueStore.querySingleEventsTrackedEntityDataValues(); List events = filteredEvents == null ? eventStore.querySingleEventsToPost() : filteredEvents; - List eventRecreated = new ArrayList<>(); + List notes = queryNotesToSync(); + List eventRecreated = new ArrayList<>(); for (Event event : events) { List dataValuesForEvent = dataValueMap.get(event.uid()); + List eventNotes = getEventNotes(notes, event.uid()); + + Event.Builder eventBuilder = event.toBuilder() + .trackedEntityDataValues(dataValuesForEvent) + .notes(eventNotes); if (versionManager.is2_30()) { - eventRecreated.add(event.toBuilder() - .trackedEntityDataValues(dataValuesForEvent) - .geometry(null) - .build()); - } else { - eventRecreated.add(event.toBuilder().trackedEntityDataValues(dataValuesForEvent).build()); + eventBuilder.geometry(null); } + eventRecreated.add(eventBuilder.build()); } markPartitionsAsUploading(eventRecreated); @@ -139,6 +151,25 @@ List queryDataToSync(List filteredEvents) { return eventRecreated; } + private List queryNotesToSync() { + String whereNotesClause = new WhereClauseBuilder() + .appendInKeyStringValues( + DataColumns.STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())) + .appendKeyStringValue(NoteTableInfo.Columns.NOTE_TYPE, Note.NoteType.EVENT_NOTE) + .build(); + return noteStore.selectWhere(whereNotesClause); + } + + private List getEventNotes(List allNotes, String eventUid) { + List eventNotes = new ArrayList<>(); + for (Note note : allNotes) { + if (eventUid.equals(note.event())) { + eventNotes.add(note); + } + } + return eventNotes; + } + private void handleWebResponse(EventWebResponse webResponse) { if (webResponse == null || webResponse.response() == null) { return; diff --git a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCall.java b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCall.java index 9a1428b686..672ed38f45 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCall.java +++ b/core/src/main/java/org/hisp/dhis/android/core/trackedentity/internal/TrackedEntityInstancePostCall.java @@ -37,6 +37,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; import org.hisp.dhis.android.core.arch.helpers.CollectionsHelper; import org.hisp.dhis.android.core.arch.helpers.UidsHelper; +import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; import org.hisp.dhis.android.core.common.CoreColumns; import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.State; @@ -197,7 +198,9 @@ List> getPartitionsToSync(List> attributeValueMap = trackedEntityAttributeValueStore.queryTrackedEntityAttributeValueToPost(); String whereNotesClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.STATE, State.TO_POST).build(); + .appendKeyStringValue( + DataColumns.STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())) + .build(); List notes = noteStore.selectWhere(whereNotesClause); List targetTrackedEntityInstances; From 267f2171fa139de331206f693a67f37fad1a1946 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Thu, 30 Apr 2020 15:23:15 +0200 Subject: [PATCH 02/10] [ANDROSDK-1133] Prevent notes to end up in ERROR state --- .../core/enrollment/internal/EnrollmentImportHandler.java | 7 +++++-- .../android/core/event/internal/EventImportHandler.java | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java index bc42223a9b..877033aa49 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/enrollment/internal/EnrollmentImportHandler.java @@ -34,6 +34,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; +import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.common.internal.DataStatePropagator; @@ -140,12 +141,14 @@ private void handleEventImportSummaries(EnrollmentImportSummary enrollmentImport } private void handleNoteImportSummary(String enrollmentUid, State state) { + State newNoteState = state.equals(State.SYNCED) ? State.SYNCED : State.TO_POST; String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.STATE, State.TO_POST) + .appendInKeyStringValues( + DataColumns.STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())) .appendKeyStringValue(NoteTableInfo.Columns.ENROLLMENT, enrollmentUid).build(); List notes = noteStore.selectWhere(whereClause); for (Note note : notes) { - noteStore.update(note.toBuilder().state(state).build()); + noteStore.update(note.toBuilder().state(newNoteState).build()); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java index 68038f3ce3..03d86f3cac 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java +++ b/core/src/main/java/org/hisp/dhis/android/core/event/internal/EventImportHandler.java @@ -34,6 +34,7 @@ import org.hisp.dhis.android.core.arch.db.stores.internal.IdentifiableObjectStore; import org.hisp.dhis.android.core.arch.db.stores.internal.ObjectStore; import org.hisp.dhis.android.core.arch.handlers.internal.HandleAction; +import org.hisp.dhis.android.core.arch.helpers.internal.EnumHelper; import org.hisp.dhis.android.core.common.DataColumns; import org.hisp.dhis.android.core.common.State; import org.hisp.dhis.android.core.enrollment.internal.EnrollmentStore; @@ -167,12 +168,14 @@ private void deleteEventConflicts(String eventUid) { } private void handleNoteImportSummary(String eventUid, State state) { + State newNoteState = state.equals(State.SYNCED) ? State.SYNCED : State.TO_POST; String whereClause = new WhereClauseBuilder() - .appendKeyStringValue(DataColumns.STATE, State.TO_POST) + .appendInKeyStringValues( + DataColumns.STATE, EnumHelper.asStringList(State.uploadableStatesIncludingError())) .appendKeyStringValue(NoteTableInfo.Columns.EVENT, eventUid).build(); List notes = noteStore.selectWhere(whereClause); for (Note note : notes) { - noteStore.update(note.toBuilder().state(state).build()); + noteStore.update(note.toBuilder().state(newNoteState).build()); } } } \ No newline at end of file From b3a00d839c437b76de797b2aae90e32add82e5b2 Mon Sep 17 00:00:00 2001 From: luis Date: Mon, 4 May 2020 11:46:42 +0200 Subject: [PATCH 03/10] [ENCRYPTION-DOC-PERFORMANCE] update encryption doc performance --- docs/content/developer/database.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/developer/database.md b/docs/content/developer/database.md index a4b9b9fa9a..7e2c44a7ab 100644 --- a/docs/content/developer/database.md +++ b/docs/content/developer/database.md @@ -23,4 +23,4 @@ if changed, will encrypt or decrypt the current database without data loss. ### Encryption performance - Database size: the database size is approximately the same, regardless of being encrypted or not. -- Speed: reads and writes are on average 25% slower using an encrypted database. \ No newline at end of file +- Speed: reads and writes are on average 5 to 10% slower using an encrypted database. \ No newline at end of file From 1def2307e0829958080bc688d97b54c40f4f078f Mon Sep 17 00:00:00 2001 From: victor Date: Mon, 4 May 2020 12:37:15 +0200 Subject: [PATCH 04/10] [ANDROSDK-1137] Do not allow D2 instantiation if keyStore fails --- .../org/hisp/dhis/android/core/D2Factory.java | 3 +- ...alsSecureStorageMockIntegrationShould.java | 3 +- .../storage/internal/AndroidSecureStore.java | 30 +++++++++++-------- .../android/core/maintenance/D2ErrorCode.java | 1 + 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/D2Factory.java b/core/src/androidTest/java/org/hisp/dhis/android/core/D2Factory.java index 29de553439..6098bfc303 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/D2Factory.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/D2Factory.java @@ -40,6 +40,7 @@ import org.hisp.dhis.android.core.arch.storage.internal.InMemoryUnsecureStore; import org.hisp.dhis.android.core.arch.storage.internal.InsecureStore; import org.hisp.dhis.android.core.arch.storage.internal.SecureStore; +import org.hisp.dhis.android.core.maintenance.D2Error; import java.util.Collections; @@ -51,7 +52,7 @@ public static D2 forNewDatabase() { return forNewDatabaseInternal(new InMemorySecureStore(), new InMemoryUnsecureStore()); } - public static D2 forNewDatabaseWithAndroidSecureStore() { + public static D2 forNewDatabaseWithAndroidSecureStore() throws D2Error { Context context = InstrumentationRegistry.getTargetContext().getApplicationContext(); return forNewDatabaseInternal(new AndroidSecureStore(context), new AndroidInsecureStore(context)); } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/core/arch/storage/internal/CredentialsSecureStorageMockIntegrationShould.java b/core/src/androidTest/java/org/hisp/dhis/android/core/arch/storage/internal/CredentialsSecureStorageMockIntegrationShould.java index 2e44de9278..a8198c7b28 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/core/arch/storage/internal/CredentialsSecureStorageMockIntegrationShould.java +++ b/core/src/androidTest/java/org/hisp/dhis/android/core/arch/storage/internal/CredentialsSecureStorageMockIntegrationShould.java @@ -30,6 +30,7 @@ import androidx.test.InstrumentationRegistry; +import org.hisp.dhis.android.core.maintenance.D2Error; import org.hisp.dhis.android.core.utils.runner.D2JunitRunner; import org.junit.Before; import org.junit.Test; @@ -43,7 +44,7 @@ public class CredentialsSecureStorageMockIntegrationShould { private ObjectKeyValueStore credentialsSecureStore; @Before - public void setUp() { + public void setUp() throws D2Error { credentialsSecureStore = new CredentialsSecureStoreImpl( new AndroidSecureStore(InstrumentationRegistry.getContext().getApplicationContext())); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java b/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java index 651b0a4617..17df63fbcb 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java @@ -37,6 +37,10 @@ import androidx.annotation.NonNull; +import org.hisp.dhis.android.core.maintenance.D2Error; +import org.hisp.dhis.android.core.maintenance.D2ErrorCode; +import org.hisp.dhis.android.core.maintenance.D2ErrorComponent; + import java.io.IOException; import java.math.BigInteger; import java.nio.charset.Charset; @@ -55,6 +59,7 @@ import java.security.cert.CertificateException; import java.security.spec.AlgorithmParameterSpec; import java.util.Calendar; +import java.util.Date; import java.util.GregorianCalendar; import javax.crypto.BadPaddingException; @@ -77,7 +82,7 @@ public final class AndroidSecureStore implements SecureStore { private final SharedPreferences preferences; - public AndroidSecureStore(Context context) { + public AndroidSecureStore(Context context) throws D2Error { preferences = context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE); KeyStore ks; @@ -95,7 +100,7 @@ public AndroidSecureStore(Context context) { } } catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException | UnrecoverableKeyException ex) { - return; + throw keyStoreError(ex, D2ErrorCode.CANT_ACCESS_KEYSTORE); } // Create a start and end time, for the validity range of the key pair that's about to be @@ -126,7 +131,7 @@ public AndroidSecureStore(Context context) { kpGenerator.generateKeyPair(); } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchProviderException e) { deleteKeyStoreEntry(ks, ALIAS); - throw new RuntimeException("Couldn't initialize AndroidSecureStore"); + throw keyStoreError(e, D2ErrorCode.CANT_ACCESS_KEYSTORE); } } @@ -134,18 +139,9 @@ public void setData(@NonNull String key, @NonNull String data) { KeyStore ks = null; try { ks = KeyStore.getInstance(KEYSTORE_PROVIDER_ANDROID_KEYSTORE); - ks.load(null); - if (ks.getCertificate(ALIAS) == null) { - return; - } - PublicKey publicKey = ks.getCertificate(ALIAS).getPublicKey(); - if (publicKey == null) { - return; - } - String value = encrypt(publicKey, data.getBytes(CHARSET)); SharedPreferences.Editor editor = preferences.edit(); @@ -211,4 +207,14 @@ private void deleteKeyStoreEntry(KeyStore ks, String entry) { Log.w("SECURE_STORE", "Cannot deleted entry " + entry); } } + + private D2Error keyStoreError(Exception ex, D2ErrorCode d2ErrorCode) { + return D2Error.builder() + .errorComponent(D2ErrorComponent.SDK) + .errorCode(d2ErrorCode) + .errorDescription(ex.getMessage()) + .originalException(ex) + .created(new Date()) + .build(); + } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java b/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java index 981d9360e1..15fcb803c0 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java +++ b/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java @@ -37,6 +37,7 @@ public enum D2ErrorCode { APP_NAME_NOT_SET, APP_VERSION_NOT_SET, BAD_CREDENTIALS, + CANT_ACCESS_KEYSTORE, CANT_CREATE_EXISTING_OBJECT, CANT_DELETE_NON_EXISTING_OBJECT, COULD_NOT_RESERVE_VALUE_ON_SERVER, From ff0489d6897b26210c4fdaaee69f5fc08dfa0ad5 Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 5 May 2020 09:10:13 +0200 Subject: [PATCH 05/10] [ANDROSDK-1138] Set default value to errorComponent --- core/src/main/assets/migrations/72.sql | 2 ++ core/src/main/assets/snapshots/{71.sql => 72.sql} | 0 .../core/arch/db/access/internal/BaseDatabaseOpenHelper.java | 2 +- .../core/arch/db/access/internal/DatabaseMigrationExecutor.java | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 core/src/main/assets/migrations/72.sql rename core/src/main/assets/snapshots/{71.sql => 72.sql} (100%) diff --git a/core/src/main/assets/migrations/72.sql b/core/src/main/assets/migrations/72.sql new file mode 100644 index 0000000000..c0a30b585b --- /dev/null +++ b/core/src/main/assets/migrations/72.sql @@ -0,0 +1,2 @@ +# Related to ANDROSDK-1138 +UPDATE D2Error SET errorComponent = 'SDK' WHERE errorComponent IS NULL; \ No newline at end of file diff --git a/core/src/main/assets/snapshots/71.sql b/core/src/main/assets/snapshots/72.sql similarity index 100% rename from core/src/main/assets/snapshots/71.sql rename to core/src/main/assets/snapshots/72.sql diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java index 12418b206d..05ba344541 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.java @@ -36,7 +36,7 @@ class BaseDatabaseOpenHelper { - static final int VERSION = 71; + static final int VERSION = 72; private final AssetManager assetManager; private final int targetVersion; diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/DatabaseMigrationExecutor.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/DatabaseMigrationExecutor.java index fd2fac3006..1dfa8748a7 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/DatabaseMigrationExecutor.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/DatabaseMigrationExecutor.java @@ -42,7 +42,7 @@ class DatabaseMigrationExecutor { private final DatabaseAdapter databaseAdapter; private final DatabaseMigrationParser parser; - private static final int SNAPSHOT_VERSION = 71; + private static final int SNAPSHOT_VERSION = 72; DatabaseMigrationExecutor(DatabaseAdapter databaseAdapter, AssetManager assetManager) { this.databaseAdapter = databaseAdapter; From 5f3191c21d1ec49ac44dd2c1bdcfe32791c0a94f Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 5 May 2020 09:37:05 +0200 Subject: [PATCH 06/10] [ANDROSDK-1137] Throw explicit exceptions --- .../storage/internal/AndroidSecureStore.java | 23 +++++++++++-------- .../android/core/maintenance/D2ErrorCode.java | 1 + 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java b/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java index 17df63fbcb..01c69bab71 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java @@ -131,7 +131,7 @@ public AndroidSecureStore(Context context) throws D2Error { kpGenerator.generateKeyPair(); } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | NoSuchProviderException e) { deleteKeyStoreEntry(ks, ALIAS); - throw keyStoreError(e, D2ErrorCode.CANT_ACCESS_KEYSTORE); + throw keyStoreError(e, D2ErrorCode.CANT_INSTANTIATE_KEYSTORE); } } @@ -140,18 +140,25 @@ public void setData(@NonNull String key, @NonNull String data) { try { ks = KeyStore.getInstance(KEYSTORE_PROVIDER_ANDROID_KEYSTORE); ks.load(null); + + if (ks.getCertificate(ALIAS) == null) { + throw new RuntimeException("Couldn't find certificate for key: " + key); + } + PublicKey publicKey = ks.getCertificate(ALIAS).getPublicKey(); + if (publicKey == null) { + throw new RuntimeException("Couldn't find publicKey for key: " + key); + } + String value = encrypt(publicKey, data.getBytes(CHARSET)); SharedPreferences.Editor editor = preferences.edit(); editor.putString(key, value); editor.apply(); - } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException - | IllegalBlockSizeException | BadPaddingException | KeyStoreException | - CertificateException | IOException e) { + } catch (Exception e) { deleteKeyStoreEntry(ks, ALIAS); - throw new RuntimeException("Couldn't store value in AndroidSecureStore for key: " + key); + throw new RuntimeException("Couldn't store value in AndroidSecureStore for key: " + key, e); } } @@ -165,11 +172,9 @@ public String getData(@NonNull String key) { return value == null ? null : new String(decrypt(privateKey, value), CHARSET); - } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException - | UnrecoverableEntryException | InvalidKeyException | NoSuchPaddingException - | IllegalBlockSizeException | BadPaddingException e) { + } catch (Exception e) { deleteKeyStoreEntry(ks, ALIAS); - throw new RuntimeException("Couldn't get value from AndroidSecureStore for key: " + key); + throw new RuntimeException("Couldn't get value from AndroidSecureStore for key: " + key, e); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java b/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java index 15fcb803c0..ddcd21b568 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java +++ b/core/src/main/java/org/hisp/dhis/android/core/maintenance/D2ErrorCode.java @@ -40,6 +40,7 @@ public enum D2ErrorCode { CANT_ACCESS_KEYSTORE, CANT_CREATE_EXISTING_OBJECT, CANT_DELETE_NON_EXISTING_OBJECT, + CANT_INSTANTIATE_KEYSTORE, COULD_NOT_RESERVE_VALUE_ON_SERVER, FILE_NOT_FOUND, FAIL_RESIZING_IMAGE, From 8f4a1890f14e2657d4908b602c51382e6c8b7a29 Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 5 May 2020 10:26:40 +0200 Subject: [PATCH 07/10] [ANDROSDK-1137] PMD --- .../android/core/arch/storage/internal/AndroidSecureStore.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java b/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java index 01c69bab71..3df7ebd961 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java @@ -54,7 +54,6 @@ import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; -import java.security.UnrecoverableEntryException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.spec.AlgorithmParameterSpec; From 49e3d9695a98df1bdf31c2f7dc96e6a1e4579a52 Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 5 May 2020 12:25:08 +0200 Subject: [PATCH 08/10] [ANDROSDK-1137] Explict exception types --- .../core/arch/storage/internal/AndroidSecureStore.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java b/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java index 3df7ebd961..518e8c4d3e 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/storage/internal/AndroidSecureStore.java @@ -54,6 +54,7 @@ import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; +import java.security.UnrecoverableEntryException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.spec.AlgorithmParameterSpec; @@ -155,7 +156,9 @@ public void setData(@NonNull String key, @NonNull String data) { SharedPreferences.Editor editor = preferences.edit(); editor.putString(key, value); editor.apply(); - } catch (Exception e) { + } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException + | IllegalBlockSizeException | BadPaddingException | KeyStoreException | + CertificateException | IOException e) { deleteKeyStoreEntry(ks, ALIAS); throw new RuntimeException("Couldn't store value in AndroidSecureStore for key: " + key, e); } @@ -171,7 +174,9 @@ public String getData(@NonNull String key) { return value == null ? null : new String(decrypt(privateKey, value), CHARSET); - } catch (Exception e) { + } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException + | UnrecoverableEntryException | InvalidKeyException | NoSuchPaddingException + | IllegalBlockSizeException | BadPaddingException e) { deleteKeyStoreEntry(ks, ALIAS); throw new RuntimeException("Couldn't get value from AndroidSecureStore for key: " + key, e); } From b34191b6abcfc7994792a88bbbe6730d3623c046 Mon Sep 17 00:00:00 2001 From: luis Date: Wed, 6 May 2020 15:12:03 +0200 Subject: [PATCH 09/10] [LOGIN-DATABASE-EXCEPTION-MESSAGE] Change database not created text --- .../core/arch/db/access/internal/ParentDatabaseAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/ParentDatabaseAdapter.java b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/ParentDatabaseAdapter.java index aa33e0dc2d..a65e0315a6 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/ParentDatabaseAdapter.java +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/ParentDatabaseAdapter.java @@ -40,7 +40,7 @@ class ParentDatabaseAdapter implements DatabaseAdapter { private DatabaseAdapter getAdapter() { if (adapter == null) { - throw new RuntimeException("Database not yet created. Please login first."); + throw new RuntimeException("Please login to access the database."); } else { return adapter; } From 2f211c20ef231954656ca15e35e6d60b807765ea Mon Sep 17 00:00:00 2001 From: victor Date: Wed, 6 May 2020 15:21:11 +0200 Subject: [PATCH 10/10] [MASTER-DEV] Update references version 1.1.1 --- core/build.gradle | 4 ++-- core/gradle.properties | 4 ++-- docs/content/developer/compatibility.md | 1 + docs/content/developer/getting-started.md | 2 +- docs/dhis2_android_sdk_developer_guide_INDEX.md | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index f4f228e8e7..12f6f522ce 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -36,8 +36,8 @@ ext { buildToolsVersion: "28.0.3", minSdkVersion : 19, targetSdkVersion : 28, - versionCode : 210, - versionName : "1.1.0" + versionCode : 211, + versionName : "1.1.1" ] libraries = [ diff --git a/core/gradle.properties b/core/gradle.properties index 0b91150413..0429703b38 100644 --- a/core/gradle.properties +++ b/core/gradle.properties @@ -29,8 +29,8 @@ # Properties which are consumed by plugins/gradle-mvn-push.gradle plugin. # They are used for publishing artifact to snapshot repository. -VERSION_NAME=1.1.0 -VERSION_CODE=210 +VERSION_NAME=1.1.1 +VERSION_CODE=211 GROUP=org.hisp.dhis diff --git a/docs/content/developer/compatibility.md b/docs/content/developer/compatibility.md index eb549829b9..b0aa407c24 100644 --- a/docs/content/developer/compatibility.md +++ b/docs/content/developer/compatibility.md @@ -11,3 +11,4 @@ Compatibility table between DHIS2 Android SDK library, DHIS2 core and Android SD | 1.0.2 | 2.29 -> 2.33 | 19 - 28 | | 1.0.3 | 2.29 -> 2.33 | 19 - 28 | | 1.1.0 | 2.29 -> 2.34 | 19 - 28 | +| 1.1.1 | 2.29 -> 2.34 | 19 - 28 | diff --git a/docs/content/developer/getting-started.md b/docs/content/developer/getting-started.md index 379c66b2dd..78a00535c5 100644 --- a/docs/content/developer/getting-started.md +++ b/docs/content/developer/getting-started.md @@ -10,7 +10,7 @@ Include dependency in build.gradle. ```gradle dependencies { - implementation "org.hisp.dhis:android-core:1.1.0" + implementation "org.hisp.dhis:android-core:1.1.1" ... } ``` diff --git a/docs/dhis2_android_sdk_developer_guide_INDEX.md b/docs/dhis2_android_sdk_developer_guide_INDEX.md index bf6704c27a..792deffbd2 100644 --- a/docs/dhis2_android_sdk_developer_guide_INDEX.md +++ b/docs/dhis2_android_sdk_developer_guide_INDEX.md @@ -3,11 +3,11 @@ title: 'DHIS 2 Android SDK Developer Guide' author: 'DHIS 2' date: year: 2020 -month: April +month: May keywords: [DHIS2, Android] commit: version: master -applicable_txt: 'Applicable to version 1.1.0' +applicable_txt: 'Applicable to version 1.1.1' ---