Return full result set from external provider autocrypt_status query
This commit is contained in:
@@ -48,7 +48,7 @@ import timber.log.Timber;
|
|||||||
*/
|
*/
|
||||||
public class KeychainDatabase {
|
public class KeychainDatabase {
|
||||||
private static final String DATABASE_NAME = "openkeychain.db";
|
private static final String DATABASE_NAME = "openkeychain.db";
|
||||||
private static final int DATABASE_VERSION = 35;
|
private static final int DATABASE_VERSION = 36;
|
||||||
private final SupportSQLiteOpenHelper supportSQLiteOpenHelper;
|
private final SupportSQLiteOpenHelper supportSQLiteOpenHelper;
|
||||||
private final Database sqldelightDatabase;
|
private final Database sqldelightDatabase;
|
||||||
|
|
||||||
@@ -141,6 +141,7 @@ public class KeychainDatabase {
|
|||||||
}
|
}
|
||||||
switch (oldVersion) {
|
switch (oldVersion) {
|
||||||
case 34:
|
case 34:
|
||||||
|
case 35:
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
// recreate the unified key view on any upgrade
|
// recreate the unified key view on any upgrade
|
||||||
@@ -191,7 +192,20 @@ public class KeychainDatabase {
|
|||||||
FROM validKeys
|
FROM validKeys
|
||||||
WHERE rank = 0;
|
WHERE rank = 0;
|
||||||
""");
|
""");
|
||||||
|
db.execSQL("DROP VIEW IF EXISTS autocryptKeyStatus");
|
||||||
|
db.execSQL("""
|
||||||
|
CREATE VIEW autocryptKeyStatus AS
|
||||||
|
SELECT autocryptPeer.*,
|
||||||
|
(CASE WHEN ac_key.expiry IS NULL THEN 0 WHEN ac_key.expiry > strftime('%s', 'now') THEN 0 ELSE 1 END) AS key_is_expired_int,
|
||||||
|
(CASE WHEN gossip_key.expiry IS NULL THEN 0 WHEN gossip_key.expiry > strftime('%s', 'now') THEN 0 ELSE 1 END) AS gossip_key_is_expired_int,
|
||||||
|
ac_key.is_revoked AS key_is_revoked,
|
||||||
|
gossip_key.is_revoked AS gossip_key_is_revoked,
|
||||||
|
EXISTS (SELECT * FROM certs WHERE certs.master_key_id = autocryptPeer.master_key_id AND verified = 1) AS key_is_verified,
|
||||||
|
EXISTS (SELECT * FROM certs WHERE certs.master_key_id = autocryptPeer.gossip_master_key_id AND verified = 1) AS gossip_key_is_verified
|
||||||
|
FROM autocrypt_peers AS autocryptPeer
|
||||||
|
LEFT JOIN keys AS ac_key ON (ac_key.master_key_id = autocryptPeer.master_key_id AND ac_key.rank = 0)
|
||||||
|
LEFT JOIN keys AS gossip_key ON (gossip_key.master_key_id = gossip_master_key_id AND gossip_key.rank = 0);
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onDowngrade() {
|
private void onDowngrade() {
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ import java.util.List;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import org.sufficientlysecure.keychain.AutocryptKeyStatus;
|
||||||
import org.sufficientlysecure.keychain.AutocryptPeersQueries;
|
import org.sufficientlysecure.keychain.AutocryptPeersQueries;
|
||||||
import org.sufficientlysecure.keychain.Autocrypt_peers;
|
import org.sufficientlysecure.keychain.Autocrypt_peers;
|
||||||
import org.sufficientlysecure.keychain.KeychainDatabase;
|
import org.sufficientlysecure.keychain.KeychainDatabase;
|
||||||
import org.sufficientlysecure.keychain.SelectAutocryptKeyStatus;
|
|
||||||
import org.sufficientlysecure.keychain.SelectMasterKeyIdByIdentifier;
|
import org.sufficientlysecure.keychain.SelectMasterKeyIdByIdentifier;
|
||||||
import org.sufficientlysecure.keychain.model.GossipOrigin;
|
import org.sufficientlysecure.keychain.model.GossipOrigin;
|
||||||
|
|
||||||
@@ -71,12 +71,17 @@ public class AutocryptPeerDao extends AbstractDao {
|
|||||||
.executeAsList();
|
.executeAsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SelectAutocryptKeyStatus> getAutocryptKeyStatus(String packageName,
|
public List<AutocryptKeyStatus> getAutocryptKeyStatus(String packageName,
|
||||||
String[] autocryptIds) {
|
String[] autocryptIds) {
|
||||||
return autocryptPeersQueries.selectAutocryptKeyStatus(packageName,
|
return autocryptPeersQueries.selectAutocryptKeyStatus(packageName,
|
||||||
Arrays.asList(autocryptIds)).executeAsList();
|
Arrays.asList(autocryptIds)).executeAsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<AutocryptKeyStatus> getAutocryptKeyStatusLike(String packageName,
|
||||||
|
String query) {
|
||||||
|
return autocryptPeersQueries.selectAutocryptKeyStatusLike(packageName, query).executeAsList();
|
||||||
|
}
|
||||||
|
|
||||||
private void ensureAutocryptPeerExists(String packageName, String autocryptId) {
|
private void ensureAutocryptPeerExists(String packageName, String autocryptId) {
|
||||||
autocryptPeersQueries.insertPeer(packageName, autocryptId);
|
autocryptPeersQueries.insertPeer(packageName, autocryptId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,6 @@ public class UserIdDao extends AbstractDao {
|
|||||||
.executeAsList();
|
.executeAsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UidStatus getUidStatusByEmailLike(String emailLike) {
|
|
||||||
return getDatabase().getUserPacketsQueries().selectUserIdStatusByEmailLike(emailLike)
|
|
||||||
.executeAsOneOrNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, UidStatus> getUidStatusByEmail(String... emails) {
|
public Map<String, UidStatus> getUidStatusByEmail(String... emails) {
|
||||||
Query<UidStatus> q = getDatabase().getUserPacketsQueries()
|
Query<UidStatus> q = getDatabase().getUserPacketsQueries()
|
||||||
.selectUserIdStatusByEmail(Arrays.asList(emails));
|
.selectUserIdStatusByEmail(Arrays.asList(emails));
|
||||||
@@ -54,6 +49,21 @@ public class UserIdDao extends AbstractDao {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, UidStatus> getUidStatusByEmailLike(String query) {
|
||||||
|
Query<UidStatus> q = getDatabase().getUserPacketsQueries()
|
||||||
|
.selectUserIdStatusByEmailLike(query);
|
||||||
|
Map<String, UidStatus> result = new HashMap<>();
|
||||||
|
try (SqlCursor cursor = q.execute()) {
|
||||||
|
while (cursor.next()) {
|
||||||
|
UidStatus item = q.getMapper().invoke(cursor);
|
||||||
|
result.put(item.getEmail(), item);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// oops
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private List<Long> getLongArrayAsList(long[] longList) {
|
private List<Long> getLongArrayAsList(long[] longList) {
|
||||||
Long[] longs = new Long[longList.length];
|
Long[] longs = new Long[longList.length];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import android.text.format.DateUtils;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import org.openintents.openpgp.AutocryptPeerUpdate;
|
import org.openintents.openpgp.AutocryptPeerUpdate;
|
||||||
import org.openintents.openpgp.AutocryptPeerUpdate.PreferEncrypt;
|
import org.openintents.openpgp.AutocryptPeerUpdate.PreferEncrypt;
|
||||||
|
import org.sufficientlysecure.keychain.AutocryptKeyStatus;
|
||||||
import org.sufficientlysecure.keychain.Autocrypt_peers;
|
import org.sufficientlysecure.keychain.Autocrypt_peers;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.SelectAutocryptKeyStatus;
|
|
||||||
import org.sufficientlysecure.keychain.daos.AutocryptPeerDao;
|
import org.sufficientlysecure.keychain.daos.AutocryptPeerDao;
|
||||||
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
|
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
|
||||||
import org.sufficientlysecure.keychain.model.GossipOrigin;
|
import org.sufficientlysecure.keychain.model.GossipOrigin;
|
||||||
@@ -150,7 +150,18 @@ public class AutocryptInteractor {
|
|||||||
public Map<String,AutocryptRecommendationResult> determineAutocryptRecommendations(String... autocryptIds) {
|
public Map<String,AutocryptRecommendationResult> determineAutocryptRecommendations(String... autocryptIds) {
|
||||||
Map<String,AutocryptRecommendationResult> result = new HashMap<>(autocryptIds.length);
|
Map<String,AutocryptRecommendationResult> result = new HashMap<>(autocryptIds.length);
|
||||||
|
|
||||||
for (SelectAutocryptKeyStatus autocryptKeyStatus : autocryptPeerDao.getAutocryptKeyStatus(packageName, autocryptIds)) {
|
for (AutocryptKeyStatus autocryptKeyStatus : autocryptPeerDao.getAutocryptKeyStatus(packageName, autocryptIds)) {
|
||||||
|
AutocryptRecommendationResult peerResult = determineAutocryptRecommendation(autocryptKeyStatus);
|
||||||
|
result.put(peerResult.peerId, peerResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableMap(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String,AutocryptRecommendationResult> determineAutocryptRecommendationsLike(String query) {
|
||||||
|
Map<String,AutocryptRecommendationResult> result = new HashMap<>();
|
||||||
|
|
||||||
|
for (AutocryptKeyStatus autocryptKeyStatus : autocryptPeerDao.getAutocryptKeyStatusLike(packageName, query)) {
|
||||||
AutocryptRecommendationResult peerResult = determineAutocryptRecommendation(autocryptKeyStatus);
|
AutocryptRecommendationResult peerResult = determineAutocryptRecommendation(autocryptKeyStatus);
|
||||||
result.put(peerResult.peerId, peerResult);
|
result.put(peerResult.peerId, peerResult);
|
||||||
}
|
}
|
||||||
@@ -162,7 +173,7 @@ public class AutocryptInteractor {
|
|||||||
* See https://autocrypt.org/level1.html#recommendations-for-single-recipient-messages
|
* See https://autocrypt.org/level1.html#recommendations-for-single-recipient-messages
|
||||||
*/
|
*/
|
||||||
private AutocryptRecommendationResult determineAutocryptRecommendation(
|
private AutocryptRecommendationResult determineAutocryptRecommendation(
|
||||||
SelectAutocryptKeyStatus autocryptKeyStatus) {
|
AutocryptKeyStatus autocryptKeyStatus) {
|
||||||
AutocryptRecommendationResult keyRecommendation = determineAutocryptKeyRecommendation(autocryptKeyStatus);
|
AutocryptRecommendationResult keyRecommendation = determineAutocryptKeyRecommendation(autocryptKeyStatus);
|
||||||
if (keyRecommendation != null) return keyRecommendation;
|
if (keyRecommendation != null) return keyRecommendation;
|
||||||
|
|
||||||
@@ -174,7 +185,7 @@ public class AutocryptInteractor {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private AutocryptRecommendationResult determineAutocryptKeyRecommendation(
|
private AutocryptRecommendationResult determineAutocryptKeyRecommendation(
|
||||||
SelectAutocryptKeyStatus autocryptKeyStatus) {
|
AutocryptKeyStatus autocryptKeyStatus) {
|
||||||
Long masterKeyId = autocryptKeyStatus.getMaster_key_id();
|
Long masterKeyId = autocryptKeyStatus.getMaster_key_id();
|
||||||
boolean hasKey = masterKeyId != null;
|
boolean hasKey = masterKeyId != null;
|
||||||
boolean isRevoked = Boolean.TRUE.equals(autocryptKeyStatus.getKey_is_revoked());
|
boolean isRevoked = Boolean.TRUE.equals(autocryptKeyStatus.getKey_is_revoked());
|
||||||
@@ -202,7 +213,7 @@ public class AutocryptInteractor {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private AutocryptRecommendationResult determineAutocryptGossipRecommendation(
|
private AutocryptRecommendationResult determineAutocryptGossipRecommendation(
|
||||||
SelectAutocryptKeyStatus autocryptKeyStatus) {
|
AutocryptKeyStatus autocryptKeyStatus) {
|
||||||
boolean gossipHasKey = autocryptKeyStatus.getGossip_master_key_id() != null;
|
boolean gossipHasKey = autocryptKeyStatus.getGossip_master_key_id() != null;
|
||||||
boolean gossipIsRevoked =
|
boolean gossipIsRevoked =
|
||||||
Boolean.TRUE.equals(autocryptKeyStatus.getGossip_key_is_revoked());
|
Boolean.TRUE.equals(autocryptKeyStatus.getGossip_key_is_revoked());
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ package org.sufficientlysecure.keychain.remote;
|
|||||||
|
|
||||||
import java.security.AccessControlException;
|
import java.security.AccessControlException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
@@ -128,30 +129,31 @@ public class KeychainExternalProvider extends ContentProvider {
|
|||||||
List<String> plist = Arrays.asList(projection);
|
List<String> plist = Arrays.asList(projection);
|
||||||
boolean isWildcardSelector =
|
boolean isWildcardSelector =
|
||||||
selectionArgs.length == 1 && selectionArgs[0].contains("%");
|
selectionArgs.length == 1 && selectionArgs[0].contains("%");
|
||||||
boolean queriesUidResult = plist.contains(AutocryptStatus.UID_KEY_STATUS) ||
|
|
||||||
plist.contains(AutocryptStatus.UID_ADDRESS) ||
|
UserIdDao userIdDao = UserIdDao.getInstance(getContext());
|
||||||
plist.contains(AutocryptStatus.UID_MASTER_KEY_ID) ||
|
AutocryptInteractor autocryptInteractor =
|
||||||
plist.contains(AutocryptStatus.UID_CANDIDATES);
|
AutocryptInteractor.getInstance(getContext(), callingPackageName);
|
||||||
boolean queriesAutocryptResult =
|
|
||||||
plist.contains(AutocryptStatus.AUTOCRYPT_PEER_STATE) ||
|
Map<String, UidStatus> uidStatuses;
|
||||||
plist.contains(AutocryptStatus.AUTOCRYPT_MASTER_KEY_ID) ||
|
Map<String, AutocryptRecommendationResult> autocryptStates;
|
||||||
plist.contains(AutocryptStatus.AUTOCRYPT_KEY_STATUS);
|
String[] emails;
|
||||||
if (isWildcardSelector && queriesAutocryptResult) {
|
if (isWildcardSelector) {
|
||||||
throw new UnsupportedOperationException(
|
uidStatuses = userIdDao.getUidStatusByEmailLike(selectionArgs[0]);
|
||||||
"Cannot wildcard-query autocrypt results!");
|
autocryptStates = autocryptInteractor.determineAutocryptRecommendationsLike(selectionArgs[0]);
|
||||||
|
// If this was a wildcard query, use the found email addresses in the result set.
|
||||||
|
Set<String> emailsSet = new HashSet<>();
|
||||||
|
emailsSet.addAll(uidStatuses.keySet());
|
||||||
|
emailsSet.addAll(autocryptStates.keySet());
|
||||||
|
emails = emailsSet.toArray(new String[0]);
|
||||||
|
} else {
|
||||||
|
uidStatuses = userIdDao.getUidStatusByEmail(selectionArgs);
|
||||||
|
autocryptStates = autocryptInteractor.determineAutocryptRecommendations(selectionArgs);
|
||||||
|
// Otherwise, map exactly the selection args to results.
|
||||||
|
emails = selectionArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, UidStatus> uidStatuses = queriesUidResult ?
|
MatrixCursor cursor = mapResultsToProjectedMatrixCursor(
|
||||||
loadUidStatusMap(selectionArgs, isWildcardSelector) :
|
projection, emails, uidStatuses, autocryptStates);
|
||||||
Collections.emptyMap();
|
|
||||||
Map<String, AutocryptRecommendationResult> autocryptStates =
|
|
||||||
queriesAutocryptResult ?
|
|
||||||
loadAutocryptRecommendationMap(selectionArgs, callingPackageName) :
|
|
||||||
Collections.emptyMap();
|
|
||||||
|
|
||||||
MatrixCursor cursor =
|
|
||||||
mapResultsToProjectedMatrixCursor(projection, selectionArgs, uidStatuses,
|
|
||||||
autocryptStates);
|
|
||||||
|
|
||||||
uri = DatabaseNotifyManager.getNotifyUriAllKeys();
|
uri = DatabaseNotifyManager.getNotifyUriAllKeys();
|
||||||
cursor.setNotificationUri(context.getContentResolver(), uri);
|
cursor.setNotificationUri(context.getContentResolver(), uri);
|
||||||
@@ -166,20 +168,22 @@ public class KeychainExternalProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private MatrixCursor mapResultsToProjectedMatrixCursor(String[] projection,
|
private MatrixCursor mapResultsToProjectedMatrixCursor(
|
||||||
String[] selectionArgs,
|
String[] projection,
|
||||||
|
String[] addresses,
|
||||||
Map<String, UidStatus> uidStatuses,
|
Map<String, UidStatus> uidStatuses,
|
||||||
Map<String, AutocryptRecommendationResult> autocryptStates) {
|
Map<String, AutocryptRecommendationResult> autocryptStates
|
||||||
|
) {
|
||||||
MatrixCursor cursor = new MatrixCursor(projection);
|
MatrixCursor cursor = new MatrixCursor(projection);
|
||||||
for (String selectionArg : selectionArgs) {
|
for (String address : addresses) {
|
||||||
AutocryptRecommendationResult autocryptResult = autocryptStates.get(selectionArg);
|
AutocryptRecommendationResult autocryptResult = autocryptStates.get(address);
|
||||||
UidStatus uidStatus = uidStatuses.get(selectionArg);
|
UidStatus uidStatus = uidStatuses.get(address);
|
||||||
|
|
||||||
Object[] row = new Object[projection.length];
|
Object[] row = new Object[projection.length];
|
||||||
for (int i = 0; i < projection.length; i++) {
|
for (int i = 0; i < projection.length; i++) {
|
||||||
if (AutocryptStatus.ADDRESS.equals(projection[i]) ||
|
if (AutocryptStatus.ADDRESS.equals(projection[i]) ||
|
||||||
AutocryptStatus._ID.equals(projection[i])) {
|
AutocryptStatus._ID.equals(projection[i])) {
|
||||||
row[i] = selectionArg;
|
row[i] = address;
|
||||||
} else {
|
} else {
|
||||||
row[i] = columnNameToRowContent(projection[i], autocryptResult, uidStatus);
|
row[i] = columnNameToRowContent(projection[i], autocryptResult, uidStatus);
|
||||||
}
|
}
|
||||||
@@ -244,25 +248,6 @@ public class KeychainExternalProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, org.sufficientlysecure.keychain.UidStatus> loadUidStatusMap(
|
|
||||||
String[] selectionArgs, boolean isWildcardSelector) {
|
|
||||||
UserIdDao userIdDao = UserIdDao.getInstance(getContext());
|
|
||||||
if (isWildcardSelector) {
|
|
||||||
org.sufficientlysecure.keychain.UidStatus uidStatus =
|
|
||||||
userIdDao.getUidStatusByEmailLike(selectionArgs[0]);
|
|
||||||
return Collections.singletonMap(selectionArgs[0], uidStatus);
|
|
||||||
} else {
|
|
||||||
return userIdDao.getUidStatusByEmail(selectionArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, AutocryptRecommendationResult> loadAutocryptRecommendationMap(
|
|
||||||
String[] selectionArgs, String callingPackageName) {
|
|
||||||
AutocryptInteractor autocryptInteractor =
|
|
||||||
AutocryptInteractor.getInstance(getContext(), callingPackageName);
|
|
||||||
return autocryptInteractor.determineAutocryptRecommendations(selectionArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getPeerStateValue(AutocryptState autocryptState) {
|
private int getPeerStateValue(AutocryptState autocryptState) {
|
||||||
switch (autocryptState) {
|
switch (autocryptState) {
|
||||||
case DISABLE:
|
case DISABLE:
|
||||||
|
|||||||
@@ -50,8 +50,9 @@ UPDATE autocrypt_peers SET gossip_last_seen_key = ?3, gossip_master_key_id = ?4,
|
|||||||
insertPeer:
|
insertPeer:
|
||||||
INSERT OR IGNORE INTO autocrypt_peers (package_name, identifier) VALUES (?, ?);
|
INSERT OR IGNORE INTO autocrypt_peers (package_name, identifier) VALUES (?, ?);
|
||||||
|
|
||||||
selectAutocryptKeyStatus:
|
autocryptKeyStatus:
|
||||||
SELECT autocryptPeer.*,
|
CREATE VIEW autocryptKeyStatus AS
|
||||||
|
SELECT autocryptPeer.*,
|
||||||
(CASE WHEN ac_key.expiry IS NULL THEN 0 WHEN ac_key.expiry > strftime('%s', 'now') THEN 0 ELSE 1 END) AS key_is_expired_int,
|
(CASE WHEN ac_key.expiry IS NULL THEN 0 WHEN ac_key.expiry > strftime('%s', 'now') THEN 0 ELSE 1 END) AS key_is_expired_int,
|
||||||
(CASE WHEN gossip_key.expiry IS NULL THEN 0 WHEN gossip_key.expiry > strftime('%s', 'now') THEN 0 ELSE 1 END) AS gossip_key_is_expired_int,
|
(CASE WHEN gossip_key.expiry IS NULL THEN 0 WHEN gossip_key.expiry > strftime('%s', 'now') THEN 0 ELSE 1 END) AS gossip_key_is_expired_int,
|
||||||
ac_key.is_revoked AS key_is_revoked,
|
ac_key.is_revoked AS key_is_revoked,
|
||||||
@@ -60,5 +61,10 @@ SELECT autocryptPeer.*,
|
|||||||
EXISTS (SELECT * FROM certs WHERE certs.master_key_id = autocryptPeer.gossip_master_key_id AND verified = 1) AS gossip_key_is_verified
|
EXISTS (SELECT * FROM certs WHERE certs.master_key_id = autocryptPeer.gossip_master_key_id AND verified = 1) AS gossip_key_is_verified
|
||||||
FROM autocrypt_peers AS autocryptPeer
|
FROM autocrypt_peers AS autocryptPeer
|
||||||
LEFT JOIN keys AS ac_key ON (ac_key.master_key_id = autocryptPeer.master_key_id AND ac_key.rank = 0)
|
LEFT JOIN keys AS ac_key ON (ac_key.master_key_id = autocryptPeer.master_key_id AND ac_key.rank = 0)
|
||||||
LEFT JOIN keys AS gossip_key ON (gossip_key.master_key_id = gossip_master_key_id AND gossip_key.rank = 0)
|
LEFT JOIN keys AS gossip_key ON (gossip_key.master_key_id = gossip_master_key_id AND gossip_key.rank = 0);
|
||||||
WHERE package_name = ?1 AND identifier IN ?2;
|
|
||||||
|
selectAutocryptKeyStatus:
|
||||||
|
SELECT * FROM autocryptKeyStatus WHERE package_name = ?1 AND identifier IN ?2;
|
||||||
|
|
||||||
|
selectAutocryptKeyStatusLike:
|
||||||
|
SELECT * FROM autocryptKeyStatus WHERE package_name = ?1 AND identifier LIKE ?2;
|
||||||
@@ -264,6 +264,60 @@ public class KeychainExternalProviderTest {
|
|||||||
assertFalse(cursor.moveToNext());
|
assertFalse(cursor.moveToNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAutocryptStatus_autocryptPeer_wildcard() throws Exception {
|
||||||
|
insertSecretKeyringFrom("/test-keys/testring.sec");
|
||||||
|
insertPublicKeyringFrom("/test-keys/testring.pub");
|
||||||
|
|
||||||
|
autocryptPeerDao.insertOrUpdateLastSeen(PACKAGE_NAME, "tid", new Date());
|
||||||
|
autocryptPeerDao.updateKey(PACKAGE_NAME, AUTOCRYPT_PEER, new Date(), KEY_ID_PUBLIC, false);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(
|
||||||
|
AutocryptStatus.CONTENT_URI, new String[] {
|
||||||
|
AutocryptStatus.ADDRESS, AutocryptStatus.UID_KEY_STATUS, AutocryptStatus.UID_ADDRESS,
|
||||||
|
AutocryptStatus.AUTOCRYPT_PEER_STATE,
|
||||||
|
AutocryptStatus.AUTOCRYPT_KEY_STATUS, AutocryptStatus.AUTOCRYPT_MASTER_KEY_ID
|
||||||
|
},
|
||||||
|
null, new String [] { "twi@%" }, null
|
||||||
|
);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
assertEquals("twi@openkeychain.org", cursor.getString(0));
|
||||||
|
assertFalse(cursor.moveToNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAutocryptStatus_autocryptPeer_wildcard2() throws Exception {
|
||||||
|
insertSecretKeyringFrom("/test-keys/testring.sec");
|
||||||
|
insertPublicKeyringFrom("/test-keys/testring.pub");
|
||||||
|
|
||||||
|
autocryptPeerDao.insertOrUpdateLastSeen(PACKAGE_NAME, "tid1", new Date());
|
||||||
|
autocryptPeerDao.insertOrUpdateLastSeen(PACKAGE_NAME, "tid2", new Date());
|
||||||
|
autocryptPeerDao.updateKey(PACKAGE_NAME, "tid1", new Date(), KEY_ID_PUBLIC, false);
|
||||||
|
autocryptPeerDao.updateKey(PACKAGE_NAME, "tid2", new Date(), KEY_ID_PUBLIC, false);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(
|
||||||
|
AutocryptStatus.CONTENT_URI, new String[] {
|
||||||
|
AutocryptStatus.ADDRESS, AutocryptStatus.UID_KEY_STATUS,
|
||||||
|
AutocryptStatus.AUTOCRYPT_PEER_STATE,
|
||||||
|
AutocryptStatus.AUTOCRYPT_KEY_STATUS, AutocryptStatus.AUTOCRYPT_MASTER_KEY_ID
|
||||||
|
},
|
||||||
|
null, new String [] { "ti%" }, null
|
||||||
|
);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
assertEquals("tid1", cursor.getString(0));
|
||||||
|
assertTrue(cursor.isNull(1));
|
||||||
|
assertEquals(KEY_ID_PUBLIC, cursor.getLong(4));
|
||||||
|
assertTrue(cursor.moveToNext());
|
||||||
|
assertEquals("tid2", cursor.getString(0));
|
||||||
|
assertTrue(cursor.isNull(1));
|
||||||
|
assertEquals(KEY_ID_PUBLIC, cursor.getLong(4));
|
||||||
|
assertFalse(cursor.moveToNext());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@Test
|
@Test
|
||||||
public void testAutocryptStatus_stateSelected() throws Exception {
|
public void testAutocryptStatus_stateSelected() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user