From 3150d2d3f9b1a47510a79c225d86121f265283bc Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 9 Jul 2018 14:29:53 +0200 Subject: [PATCH] move UidStatus querying logic into UserIdDao --- .../keychain/daos/AbstractDao.java | 11 +-- .../keychain/daos/KeyRepository.java | 28 +++--- .../keychain/daos/UserIdDao.java | 26 ++++++ .../remote/KeychainExternalProvider.java | 90 +++++++------------ 4 files changed, 78 insertions(+), 77 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/UserIdDao.java diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/AbstractDao.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/AbstractDao.java index 2daedcdcd..4500e4a75 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/AbstractDao.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/AbstractDao.java @@ -8,6 +8,7 @@ import android.arch.persistence.db.SupportSQLiteDatabase; import android.arch.persistence.db.SupportSQLiteQuery; import android.database.Cursor; +import com.squareup.sqldelight.RowMapper; import org.sufficientlysecure.keychain.KeychainDatabase; import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException; @@ -33,7 +34,7 @@ class AbstractDao { return databaseNotifyManager; } - List mapAllRows(SupportSQLiteQuery query, Mapper mapper) { + List mapAllRows(SupportSQLiteQuery query, RowMapper mapper) { ArrayList result = new ArrayList<>(); try (Cursor cursor = getReadableDb().query(query)) { while (cursor.moveToNext()) { @@ -44,7 +45,7 @@ class AbstractDao { return result; } - T mapSingleRowOrThrow(SupportSQLiteQuery query, Mapper mapper) throws NotFoundException { + T mapSingleRowOrThrow(SupportSQLiteQuery query, RowMapper mapper) throws NotFoundException { T result = mapSingleRow(query, mapper); if (result == null) { throw new NotFoundException(); @@ -52,7 +53,7 @@ class AbstractDao { return result; } - T mapSingleRow(SupportSQLiteQuery query, Mapper mapper) { + T mapSingleRow(SupportSQLiteQuery query, RowMapper mapper) { try (Cursor cursor = getReadableDb().query(query)) { if (cursor.moveToNext()) { return mapper.map(cursor); @@ -60,8 +61,4 @@ class AbstractDao { } return null; } - - interface Mapper { - T map(Cursor cursor); - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/KeyRepository.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/KeyRepository.java index d31340d4d..4fb17f818 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/KeyRepository.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/KeyRepository.java @@ -129,48 +129,48 @@ public class KeyRepository extends AbstractDao { public List getAllMasterKeyIds() { SqlDelightQuery query = KeyRingPublic.FACTORY.selectAllMasterKeyIds(); - return mapAllRows(query, KeyRingPublic.FACTORY.selectAllMasterKeyIdsMapper()::map); + return mapAllRows(query, KeyRingPublic.FACTORY.selectAllMasterKeyIdsMapper()); } public List getMasterKeyIdsBySigner(List signerMasterKeyIds) { long[] signerKeyIds = getLongListAsArray(signerMasterKeyIds); SqlDelightQuery query = KeySignature.FACTORY.selectMasterKeyIdsBySigner(signerKeyIds); - return mapAllRows(query, KeySignature.FACTORY.selectMasterKeyIdsBySignerMapper()::map); + return mapAllRows(query, KeySignature.FACTORY.selectMasterKeyIdsBySignerMapper()); } public Long getMasterKeyIdBySubkeyId(long subKeyId) { SqlDelightQuery query = SubKey.FACTORY.selectMasterKeyIdBySubkey(subKeyId); - return mapSingleRow(query, SubKey.FACTORY.selectMasterKeyIdBySubkeyMapper()::map); + return mapSingleRow(query, SubKey.FACTORY.selectMasterKeyIdBySubkeyMapper()); } public UnifiedKeyInfo getUnifiedKeyInfo(long masterKeyId) { SqlDelightQuery query = SubKey.FACTORY.selectUnifiedKeyInfoByMasterKeyId(masterKeyId); - return mapSingleRow(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map); + return mapSingleRow(query, SubKey.UNIFIED_KEY_INFO_MAPPER); } public List getUnifiedKeyInfo(long... masterKeyIds) { SqlDelightQuery query = SubKey.FACTORY.selectUnifiedKeyInfoByMasterKeyIds(masterKeyIds); - return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map); + return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER); } public List getUnifiedKeyInfosByMailAddress(String mailAddress) { SqlDelightQuery query = SubKey.FACTORY.selectUnifiedKeyInfoSearchMailAddress('%' + mailAddress + '%'); - return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map); + return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER); } public List getAllUnifiedKeyInfo() { SqlDelightQuery query = SubKey.FACTORY.selectAllUnifiedKeyInfo(); - return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map); + return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER); } public List getAllUnifiedKeyInfoWithSecret() { SqlDelightQuery query = SubKey.FACTORY.selectAllUnifiedKeyInfoWithSecret(); - return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER::map); + return mapAllRows(query, SubKey.UNIFIED_KEY_INFO_MAPPER); } public List getUserIds(long... masterKeyIds) { SqlDelightQuery query = UserPacket.FACTORY.selectUserIdsByMasterKeyId(masterKeyIds); - return mapAllRows(query, UserPacket.USER_ID_MAPPER::map); + return mapAllRows(query, UserPacket.USER_ID_MAPPER); } public List getConfirmedUserIds(long masterKeyId) { @@ -181,17 +181,17 @@ public class KeyRepository extends AbstractDao { public List getSubKeysByMasterKeyId(long masterKeyId) { SqlDelightQuery query = SubKey.FACTORY.selectSubkeysByMasterKeyId(masterKeyId); - return mapAllRows(query, SubKey.SUBKEY_MAPPER::map); + return mapAllRows(query, SubKey.SUBKEY_MAPPER); } public SecretKeyType getSecretKeyType(long keyId) throws NotFoundException { SqlDelightQuery query = SubKey.FACTORY.selectSecretKeyType(keyId); - return mapSingleRowOrThrow(query, SubKey.SKT_MAPPER::map); + return mapSingleRowOrThrow(query, SubKey.SKT_MAPPER); } public byte[] getFingerprintByKeyId(long keyId) throws NotFoundException { SqlDelightQuery query = SubKey.FACTORY.selectFingerprintByKeyId(keyId); - return mapSingleRowOrThrow(query, SubKey.FACTORY.selectFingerprintByKeyIdMapper()::map); + return mapSingleRowOrThrow(query, SubKey.FACTORY.selectFingerprintByKeyIdMapper()); } private byte[] getKeyRingAsArmoredData(byte[] data) throws IOException { @@ -247,12 +247,12 @@ public class KeyRepository extends AbstractDao { public long getSecretSignId(long masterKeyId) throws NotFoundException { SqlDelightQuery query = SubKey.FACTORY.selectEffectiveSignKeyIdByMasterKeyId(masterKeyId); - return mapSingleRowOrThrow(query, SubKey.FACTORY.selectEffectiveSignKeyIdByMasterKeyIdMapper()::map); + return mapSingleRowOrThrow(query, SubKey.FACTORY.selectEffectiveSignKeyIdByMasterKeyIdMapper()); } public long getSecretAuthenticationId(long masterKeyId) throws NotFoundException { SqlDelightQuery query = SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyId(masterKeyId); - return mapSingleRowOrThrow(query, SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyIdMapper()::map); + return mapSingleRowOrThrow(query, SubKey.FACTORY.selectEffectiveAuthKeyIdByMasterKeyIdMapper()); } public static class NotFoundException extends Exception { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/UserIdDao.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/UserIdDao.java new file mode 100644 index 000000000..5706f6765 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/daos/UserIdDao.java @@ -0,0 +1,26 @@ +package org.sufficientlysecure.keychain.daos; + + +import java.util.List; + +import com.squareup.sqldelight.SqlDelightQuery; +import org.sufficientlysecure.keychain.KeychainDatabase; +import org.sufficientlysecure.keychain.model.UserPacket; +import org.sufficientlysecure.keychain.model.UserPacket.UidStatus; + + +public class UserIdDao extends AbstractDao { + public UserIdDao(KeychainDatabase db, DatabaseNotifyManager databaseNotifyManager) { + super(db, databaseNotifyManager); + } + + public List getUidStatusByEmailLike(String emailLike) { + SqlDelightQuery query = UserPacket.FACTORY.selectUserIdStatusByEmailLike(emailLike); + return mapAllRows(query, UserPacket.UID_STATUS_MAPPER); + } + + public List getUidStatusByEmail(String... emails) { + SqlDelightQuery query = UserPacket.FACTORY.selectUserIdStatusByEmail(emails); + return mapAllRows(query, UserPacket.UID_STATUS_MAPPER); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/KeychainExternalProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/KeychainExternalProvider.java index fd8418dc9..8b8788f57 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/KeychainExternalProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/KeychainExternalProvider.java @@ -36,18 +36,16 @@ import android.net.Uri; import android.support.annotation.NonNull; import android.text.TextUtils; -import com.squareup.sqldelight.SqlDelightQuery; import org.sufficientlysecure.keychain.BuildConfig; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.KeychainDatabase; import org.sufficientlysecure.keychain.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.daos.ApiAppDao; import org.sufficientlysecure.keychain.daos.DatabaseNotifyManager; -import org.sufficientlysecure.keychain.model.UserPacket; +import org.sufficientlysecure.keychain.daos.UserIdDao; import org.sufficientlysecure.keychain.model.UserPacket.UidStatus; import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing.VerificationStatus; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; -import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.provider.KeychainExternalContract; import org.sufficientlysecure.keychain.provider.KeychainExternalContract.AutocryptStatus; @@ -71,24 +69,12 @@ public class KeychainExternalProvider extends ContentProvider { private ApiPermissionHelper apiPermissionHelper; - /** - * Build and return a {@link UriMatcher} that catches all {@link Uri} variations supported by - * this {@link ContentProvider}. - */ protected UriMatcher buildUriMatcher() { final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); String authority = KeychainExternalContract.CONTENT_AUTHORITY_EXTERNAL; - /* - * list email_status - * - *
-         * email_status/
-         * 
- */ matcher.addURI(authority, KeychainExternalContract.BASE_EMAIL_STATUS, EMAIL_STATUS); - matcher.addURI(authority, KeychainExternalContract.BASE_AUTOCRYPT_STATUS, AUTOCRYPT_STATUS); matcher.addURI(authority, KeychainExternalContract.BASE_AUTOCRYPT_STATUS + "/*", AUTOCRYPT_STATUS_INTERNAL); @@ -138,7 +124,8 @@ public class KeychainExternalProvider extends ContentProvider { String groupBy = null; - SupportSQLiteDatabase db = KeychainDatabase.getTemporaryInstance(getContext()).getReadableDatabase(); + KeychainDatabase temporaryDb = KeychainDatabase.getTemporaryInstance(getContext()); + SupportSQLiteDatabase db = temporaryDb.getReadableDatabase(); String callingPackageName = apiPermissionHelper.getCurrentCallingPackage(); @@ -243,28 +230,38 @@ public class KeychainExternalProvider extends ContentProvider { db.insert(TEMP_TABLE_QUERIED_ADDRESSES, SQLiteDatabase.CONFLICT_FAIL, cv); } - boolean isWildcardSelector = selectionArgs.length == 1 && selectionArgs[0].contains("%"); - List plist = Arrays.asList(projection); - + boolean isWildcardSelector = selectionArgs.length == 1 && selectionArgs[0].contains("%"); boolean queriesUidResult = plist.contains(AutocryptStatus.UID_KEY_STATUS) || plist.contains(AutocryptStatus.UID_ADDRESS) || plist.contains(AutocryptStatus.UID_MASTER_KEY_ID) || plist.contains(AutocryptStatus.UID_CANDIDATES); - if (queriesUidResult) { - fillTempTableWithUidResult(db, isWildcardSelector, selectionArgs); - } - boolean queriesAutocryptResult = plist.contains(AutocryptStatus.AUTOCRYPT_PEER_STATE) || plist.contains(AutocryptStatus.AUTOCRYPT_MASTER_KEY_ID) || plist.contains(AutocryptStatus.AUTOCRYPT_KEY_STATUS); if (isWildcardSelector && queriesAutocryptResult) { throw new UnsupportedOperationException("Cannot wildcard-query autocrypt results!"); } - if (!isWildcardSelector && queriesAutocryptResult) { + + UserIdDao userIdDao = new UserIdDao(temporaryDb, DatabaseNotifyManager.create(getContext())); + + if (queriesUidResult) { + List uidStatuses; + if (isWildcardSelector) { + uidStatuses = userIdDao.getUidStatusByEmailLike(selectionArgs[0]); + } else { + uidStatuses = userIdDao.getUidStatusByEmail(selectionArgs); + } + fillTempTableWithUidResult(db, uidStatuses, isWildcardSelector ? selectionArgs[0] : null); + } + + if (queriesAutocryptResult) { AutocryptInteractor autocryptInteractor = AutocryptInteractor.getInstance(getContext(), callingPackageName); - fillTempTableWithAutocryptRecommendations(db, autocryptInteractor, selectionArgs); + List autocryptStates = + autocryptInteractor.determineAutocryptRecommendations(selectionArgs); + + fillTempTableWithAutocryptRecommendations(db, autocryptStates); } HashMap projectionMap = new HashMap<>(); @@ -320,14 +317,6 @@ public class KeychainExternalProvider extends ContentProvider { return cursor; } - private void fillTempTableWithAutocryptRecommendations(SupportSQLiteDatabase db, - AutocryptInteractor autocryptInteractor, String[] peerIds) { - List autocryptStates = - autocryptInteractor.determineAutocryptRecommendations(peerIds); - - fillTempTableWithAutocryptRecommendations(db, autocryptStates); - } - private void fillTempTableWithAutocryptRecommendations(SupportSQLiteDatabase db, List autocryptRecommendations) { ContentValues cv = new ContentValues(); @@ -347,31 +336,20 @@ public class KeychainExternalProvider extends ContentProvider { } } - private void fillTempTableWithUidResult(SupportSQLiteDatabase db, - boolean isWildcardSelector, String[] selectionArgs) { - SqlDelightQuery query; - if (isWildcardSelector) { - query = UserPacket.FACTORY.selectUserIdStatusByEmailLike(selectionArgs[0]); - } else { - query = UserPacket.FACTORY.selectUserIdStatusByEmail(selectionArgs); - } + private void fillTempTableWithUidResult(SupportSQLiteDatabase db, List uidStatuses, String key) { + ContentValues cv = new ContentValues(); + for (UidStatus uidStatus : uidStatuses) { + int keyStatus = uidStatus.keyStatus() == VerificationStatus.VERIFIED_SECRET ? + KeychainExternalContract.KEY_STATUS_VERIFIED : KeychainExternalContract.KEY_STATUS_UNVERIFIED; - try (Cursor cursor = db.query(query)) { - ContentValues cv = new ContentValues(); - while (cursor.moveToNext()) { - UidStatus uidStatus = UserPacket.UID_STATUS_MAPPER.map(cursor); - int keyStatus = uidStatus.keyStatus() == VerificationStatus.VERIFIED_SECRET ? - KeychainExternalContract.KEY_STATUS_VERIFIED : KeychainExternalContract.KEY_STATUS_UNVERIFIED; + cv.put(AutocryptStatus.UID_ADDRESS, uidStatus.user_id()); + cv.put(AutocryptStatus.UID_MASTER_KEY_ID, uidStatus.master_key_id()); + cv.put(AutocryptStatus.UID_KEY_STATUS, keyStatus); + cv.put(AutocryptStatus.UID_CANDIDATES, uidStatus.candidates()); - cv.put(AutocryptStatus.UID_ADDRESS, uidStatus.user_id()); - cv.put(AutocryptStatus.UID_MASTER_KEY_ID, uidStatus.master_key_id()); - cv.put(AutocryptStatus.UID_KEY_STATUS, keyStatus); - cv.put(AutocryptStatus.UID_CANDIDATES, uidStatus.candidates()); - - db.update(TEMP_TABLE_QUERIED_ADDRESSES, SQLiteDatabase.CONFLICT_IGNORE, cv, - TEMP_TABLE_COLUMN_ADDRES + "= ?", - new String[] { isWildcardSelector ? selectionArgs[0] : uidStatus.email() }); - } + db.update(TEMP_TABLE_QUERIED_ADDRESSES, SQLiteDatabase.CONFLICT_IGNORE, cv, + TEMP_TABLE_COLUMN_ADDRES + "= ?", + new String[] { key != null ? key : uidStatus.email() }); } }