extract linked id loading from ContentProvider

This commit is contained in:
Vincent Breitmoser 2018-06-20 15:40:47 +02:00
parent 9ad29318e8
commit 377bf55b70
13 changed files with 183 additions and 271 deletions

View file

@ -0,0 +1,32 @@
package org.sufficientlysecure.keychain.model;
import com.google.auto.value.AutoValue;
import org.sufficientlysecure.keychain.UserPacketsModel;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
@AutoValue
public abstract class UserPacket implements UserPacketsModel {
public static final Factory<UserPacket> FACTORY = new Factory<>(AutoValue_UserPacket::new);
public static final SelectUserIdsByMasterKeyIdMapper<UserId> USER_ID_MAPPER =
FACTORY.selectUserIdsByMasterKeyIdMapper(AutoValue_UserPacket_UserId::new);
public static final SelectUserAttributesByTypeAndMasterKeyIdMapper<UserAttribute> USER_ATTRIBUTE_MAPPER =
FACTORY.selectUserAttributesByTypeAndMasterKeyIdMapper(AutoValue_UserPacket_UserAttribute::new);
@AutoValue
public static abstract class UserId implements SelectUserIdsByMasterKeyIdModel {
public boolean isVerified() {
Integer verified = verified();
return verified != null && verified == Certs.VERIFIED_SECRET;
}
}
@AutoValue
public static abstract class UserAttribute implements SelectUserAttributesByTypeAndMasterKeyIdModel {
public boolean isVerified() {
Integer verified = verified();
return verified != null && verified == Certs.VERIFIED_SECRET;
}
}
}

View file

@ -109,7 +109,6 @@ public class KeychainContract {
public static final String PATH_PUBLIC = "public"; public static final String PATH_PUBLIC = "public";
public static final String PATH_USER_IDS = "user_ids"; public static final String PATH_USER_IDS = "user_ids";
public static final String PATH_LINKED_IDS = "linked_ids";
public static final String PATH_KEYS = "keys"; public static final String PATH_KEYS = "keys";
public static final String PATH_CERTS = "certs"; public static final String PATH_CERTS = "certs";
@ -253,15 +252,6 @@ public class KeychainContract {
public static Uri buildUserIdsUri(Uri uri) { public static Uri buildUserIdsUri(Uri uri) {
return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_USER_IDS).build(); return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_USER_IDS).build();
} }
public static Uri buildLinkedIdsUri(long masterKeyId) {
return CONTENT_URI.buildUpon().appendPath(Long.toString(masterKeyId)).appendPath(PATH_LINKED_IDS).build();
}
public static Uri buildLinkedIdsUri(Uri uri) {
return CONTENT_URI.buildUpon().appendPath(uri.getPathSegments().get(1)).appendPath(PATH_LINKED_IDS).build();
}
} }
public static class Certs implements CertsColumns, BaseColumns { public static class Certs implements CertsColumns, BaseColumns {

View file

@ -25,7 +25,6 @@ import java.util.List;
import android.arch.persistence.db.SupportSQLiteDatabase; import android.arch.persistence.db.SupportSQLiteDatabase;
import android.content.ContentProvider; import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.UriMatcher; import android.content.UriMatcher;
import android.database.Cursor; import android.database.Cursor;
@ -39,7 +38,6 @@ import android.text.TextUtils;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.model.AutocryptPeer; import org.sufficientlysecure.keychain.model.AutocryptPeer;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
@ -64,7 +62,6 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
private static final int KEY_RING_USER_IDS = 202; private static final int KEY_RING_USER_IDS = 202;
private static final int KEY_RING_PUBLIC = 203; private static final int KEY_RING_PUBLIC = 203;
private static final int KEY_RING_CERTS = 205; private static final int KEY_RING_CERTS = 205;
private static final int KEY_RING_LINKED_IDS = 207;
private static final int KEY_RINGS_FIND_BY_EMAIL = 400; private static final int KEY_RINGS_FIND_BY_EMAIL = 400;
private static final int KEY_RINGS_FIND_BY_SUBKEY = 401; private static final int KEY_RINGS_FIND_BY_SUBKEY = 401;
@ -140,9 +137,6 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/"
+ KeychainContract.PATH_USER_IDS, + KeychainContract.PATH_USER_IDS,
KEY_RING_USER_IDS); KEY_RING_USER_IDS);
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/"
+ KeychainContract.PATH_LINKED_IDS,
KEY_RING_LINKED_IDS);
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/"
+ KeychainContract.PATH_PUBLIC, + KeychainContract.PATH_PUBLIC,
KEY_RING_PUBLIC); KEY_RING_PUBLIC);
@ -473,8 +467,7 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
} }
case KEY_RINGS_USER_IDS: case KEY_RINGS_USER_IDS:
case KEY_RING_USER_IDS: case KEY_RING_USER_IDS: {
case KEY_RING_LINKED_IDS: {
HashMap<String, String> projectionMap = new HashMap<>(); HashMap<String, String> projectionMap = new HashMap<>();
projectionMap.put(UserPackets._ID, Tables.USER_PACKETS + ".oid AS _id"); projectionMap.put(UserPackets._ID, Tables.USER_PACKETS + ".oid AS _id");
projectionMap.put(UserPackets.MASTER_KEY_ID, Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID); projectionMap.put(UserPackets.MASTER_KEY_ID, Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID);
@ -502,15 +495,10 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe
groupBy = Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID groupBy = Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID
+ ", " + Tables.USER_PACKETS + "." + UserPackets.RANK; + ", " + Tables.USER_PACKETS + "." + UserPackets.RANK;
if (match == KEY_RING_LINKED_IDS) { qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL");
qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " = "
+ WrappedUserAttribute.UAT_URI_ATTRIBUTE);
} else {
qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.TYPE + " IS NULL");
}
// If we are searching for a particular keyring's ids, add where // If we are searching for a particular keyring's ids, add where
if (match == KEY_RING_USER_IDS || match == KEY_RING_LINKED_IDS) { if (match == KEY_RING_USER_IDS) {
qb.appendWhere(" AND "); qb.appendWhere(" AND ");
qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = "); qb.appendWhere(Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(1)); qb.appendWhereEscapeString(uri.getPathSegments().get(1));

View file

@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.ui; package org.sufficientlysecure.keychain.ui;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
@ -42,6 +43,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.operations.results.EditKeyResult; import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
@ -179,7 +181,7 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
private void showUserIdInfo(final int position) { private void showUserIdInfo(final int position) {
final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position); final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position);
final int isVerified = mUserIdsAdapter.getIsVerified(position); final boolean isVerified = mUserIdsAdapter.getIsVerified(position) == Certs.VERIFIED_SECRET;
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
public void run() { public void run() {

View file

@ -35,12 +35,11 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.linked.UriAttribute; import org.sufficientlysecure.keychain.linked.UriAttribute;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.ViewHolder; import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.ViewHolder;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.AutocryptPeerInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo; import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.LinkedIdInfo; import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.LinkedIdInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.UserIdInfo; import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.UserIdInfo;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.AutocryptPeerInfo;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker; import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker;
@ -158,7 +157,7 @@ public class IdentityAdapter extends RecyclerView.Adapter<ViewHolder> {
public void bind(Context context, LinkedIdInfo info, boolean isSecret) { public void bind(Context context, LinkedIdInfo info, boolean isSecret) {
bindVerified(context, info, isSecret); bindVerified(context, info, isSecret);
UriAttribute uriAttribute = info.getUriAttribute(); UriAttribute uriAttribute = info.getLinkedAttribute();
bind(context, uriAttribute); bind(context, uriAttribute);
} }
@ -178,19 +177,12 @@ public class IdentityAdapter extends RecyclerView.Adapter<ViewHolder> {
private void bindVerified(Context context, IdentityInfo info, boolean isSecret) { private void bindVerified(Context context, IdentityInfo info, boolean isSecret) {
if (!isSecret) { if (!isSecret) {
switch (info.getVerified()) { if (info.isVerified()) {
case Certs.VERIFIED_SECRET: KeyFormattingUtils.setStatusImage(context, vVerified,
KeyFormattingUtils.setStatusImage(context, vVerified, null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR); } else {
break; KeyFormattingUtils.setStatusImage(context, vVerified,
case Certs.VERIFIED_SELF: null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
KeyFormattingUtils.setStatusImage(context, vVerified,
null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
break;
default:
KeyFormattingUtils.setStatusImage(context, vVerified,
null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR);
break;
} }
} }
} }

View file

@ -17,13 +17,11 @@
package org.sufficientlysecure.keychain.ui.adapter; package org.sufficientlysecure.keychain.ui.adapter;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.content.CursorLoader;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -33,7 +31,6 @@ import android.widget.ViewAnimator;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
@ -184,14 +181,4 @@ public class UserIdsAdapter extends UserAttributesAdapter {
public View newView(Context context, Cursor cursor, ViewGroup parent) { public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.view_key_adv_user_id_item, null); return mInflater.inflate(R.layout.view_key_adv_user_id_item, null);
} }
// don't show revoked user ids, irrelevant for average users
public static final String USER_IDS_WHERE = UserPackets.IS_REVOKED + " = 0";
public static CursorLoader createLoader(Context context, Uri dataUri) {
Uri baseUri = UserPackets.buildUserIdsUri(dataUri);
return new CursorLoader(context, baseUri,
UserIdsAdapter.USER_PACKETS_PROJECTION, USER_IDS_WHERE, null, null);
}
} }

View file

@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.ui.dialog; package org.sufficientlysecure.keychain.ui.dialog;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.content.DialogInterface; import android.content.DialogInterface;
@ -24,7 +25,6 @@ import android.os.Bundle;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
public class UserIdInfoDialogFragment extends DialogFragment { public class UserIdInfoDialogFragment extends DialogFragment {
private static final String ARG_IS_REVOKED = "is_revoked"; private static final String ARG_IS_REVOKED = "is_revoked";
@ -33,11 +33,11 @@ public class UserIdInfoDialogFragment extends DialogFragment {
/** /**
* Creates new instance of this dialog fragment * Creates new instance of this dialog fragment
*/ */
public static UserIdInfoDialogFragment newInstance(boolean isRevoked, int isVerified) { public static UserIdInfoDialogFragment newInstance(boolean isRevoked, boolean isVerified) {
UserIdInfoDialogFragment frag = new UserIdInfoDialogFragment(); UserIdInfoDialogFragment frag = new UserIdInfoDialogFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putBoolean(ARG_IS_REVOKED, isRevoked); args.putBoolean(ARG_IS_REVOKED, isRevoked);
args.putInt(ARG_IS_VERIFIED, isVerified); args.putBoolean(ARG_IS_VERIFIED, isVerified);
frag.setArguments(args); frag.setArguments(args);
@ -51,7 +51,7 @@ public class UserIdInfoDialogFragment extends DialogFragment {
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
final Activity activity = getActivity(); final Activity activity = getActivity();
int isVerified = getArguments().getInt(ARG_IS_VERIFIED); boolean isVerified = getArguments().getBoolean(ARG_IS_VERIFIED);
boolean isRevoked = getArguments().getBoolean(ARG_IS_REVOKED); boolean isRevoked = getArguments().getBoolean(ARG_IS_REVOKED);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
@ -62,19 +62,12 @@ public class UserIdInfoDialogFragment extends DialogFragment {
title = getString(R.string.user_id_info_revoked_title); title = getString(R.string.user_id_info_revoked_title);
message = getString(R.string.user_id_info_revoked_text); message = getString(R.string.user_id_info_revoked_text);
} else { } else {
switch (isVerified) { if (isVerified) {
case KeychainContract.Certs.VERIFIED_SECRET: title = getString(R.string.user_id_info_certified_title);
title = getString(R.string.user_id_info_certified_title); message = getString(R.string.user_id_info_certified_text);
message = getString(R.string.user_id_info_certified_text); } else {
break; title = getString(R.string.user_id_info_uncertified_title);
case KeychainContract.Certs.VERIFIED_SELF: message = getString(R.string.user_id_info_uncertified_text);
title = getString(R.string.user_id_info_uncertified_title);
message = getString(R.string.user_id_info_uncertified_text);
break;
default:
title = getString(R.string.user_id_info_invalid_title);
message = getString(R.string.user_id_info_invalid_text);
break;
} }
} }

View file

@ -18,15 +18,12 @@
package org.sufficientlysecure.keychain.ui.keyview; package org.sufficientlysecure.keychain.ui.keyview;
import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import android.arch.lifecycle.LiveData; import android.arch.lifecycle.LiveData;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@ -37,10 +34,7 @@ import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentManager.OnBackStackChangedListener; import android.support.v4.app.FragmentManager.OnBackStackChangedListener;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -62,15 +56,13 @@ import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeyRepository; import org.sufficientlysecure.keychain.provider.KeyRepository;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.service.CertifyActionsParcel; import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction; import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter; import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment; import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.keyview.LinkedIdViewFragment.ViewHolder.VerifyState; import org.sufficientlysecure.keychain.ui.keyview.LinkedIdViewFragment.ViewHolder.VerifyState;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao;
import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.LinkedIdInfo;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify;
@ -81,14 +73,11 @@ import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
import timber.log.Timber; import timber.log.Timber;
public class LinkedIdViewFragment extends CryptoOperationFragment implements public class LinkedIdViewFragment extends CryptoOperationFragment implements OnBackStackChangedListener {
LoaderManager.LoaderCallbacks<Cursor>, OnBackStackChangedListener {
private static final String ARG_DATA_URI = "data_uri";
private static final String ARG_LID_RANK = "rank"; private static final String ARG_LID_RANK = "rank";
private static final String ARG_IS_SECRET = "verified"; private static final String ARG_IS_SECRET = "verified";
private static final String ARG_MASTER_KEY_ID = "master_key_id"; private static final String ARG_MASTER_KEY_ID = "master_key_id";
private static final int LOADER_ID_LINKED_ID = 1;
private long masterKeyId; private long masterKeyId;
private boolean isSecret; private boolean isSecret;
@ -98,16 +87,14 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
private AsyncTask taskInProgress; private AsyncTask taskInProgress;
private Uri dataUri;
private ViewHolder viewHolder; private ViewHolder viewHolder;
private int lidRank; private int lidRank;
private long certifyKeyId; private long certifyKeyId;
public static LinkedIdViewFragment newInstance(Uri dataUri, int rank, boolean isSecret, long masterKeyId) { public static LinkedIdViewFragment newInstance(long masterKeyId, int rank, boolean isSecret) {
LinkedIdViewFragment frag = new LinkedIdViewFragment(); LinkedIdViewFragment frag = new LinkedIdViewFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putParcelable(ARG_DATA_URI, dataUri);
args.putInt(ARG_LID_RANK, rank); args.putInt(ARG_LID_RANK, rank);
args.putBoolean(ARG_IS_SECRET, isSecret); args.putBoolean(ARG_IS_SECRET, isSecret);
args.putLong(ARG_MASTER_KEY_ID, masterKeyId); args.putLong(ARG_MASTER_KEY_ID, masterKeyId);
@ -127,57 +114,27 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Bundle args = getArguments(); Bundle args = getArguments();
dataUri = args.getParcelable(ARG_DATA_URI);
lidRank = args.getInt(ARG_LID_RANK); lidRank = args.getInt(ARG_LID_RANK);
isSecret = args.getBoolean(ARG_IS_SECRET); isSecret = args.getBoolean(ARG_IS_SECRET);
masterKeyId = args.getLong(ARG_MASTER_KEY_ID); masterKeyId = args.getLong(ARG_MASTER_KEY_ID);
getLoaderManager().initLoader(LOADER_ID_LINKED_ID, null, this); IdentityDao identityDao = IdentityDao.getInstance(getContext());
GenericLiveData<LinkedIdInfo> uriAttributeLiveData =
new GenericLiveData<>(getContext(), null, () -> identityDao.getLinkedIdInfo(masterKeyId, lidRank));
uriAttributeLiveData.observe(this, this::onLinkedIdInfoLoaded);
} }
@Override private void onLinkedIdInfoLoaded(LinkedIdInfo linkedIdInfo) {
public Loader<Cursor> onCreateLoader(int id, Bundle args) { if (linkedIdInfo == null) {
switch (id) { Timber.e("error loading identity");
case LOADER_ID_LINKED_ID: Notify.create(getActivity(), "Error loading linked identity!",
return new CursorLoader(getContext(), dataUri, Notify.LENGTH_LONG, Style.ERROR).show();
UserIdsAdapter.USER_PACKETS_PROJECTION, finishFragment();
Tables.USER_PACKETS + "." + UserPackets.RANK return;
+ " = " + Integer.toString(lidRank), null, null);
default:
return null;
} }
}
@Override loadIdentity(linkedIdInfo.getLinkedAttribute(), linkedIdInfo.isVerified());
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
switch (loader.getId()) {
case LOADER_ID_LINKED_ID:
// Nothing to load means break if we are *expected* to load
if (!cursor.moveToFirst()) {
// Or just ignore, this is probably some intermediate state during certify
break;
}
try {
int certStatus = cursor.getInt(UserIdsAdapter.INDEX_VERIFIED);
byte[] data = cursor.getBlob(UserIdsAdapter.INDEX_ATTRIBUTE_DATA);
UriAttribute linkedId = LinkedAttribute.fromAttributeData(data);
loadIdentity(linkedId, certStatus);
} catch (IOException e) {
Timber.e(e, "error parsing identity");
Notify.create(getActivity(), "Error parsing identity!",
Notify.LENGTH_LONG, Style.ERROR).show();
finishFragment();
}
break;
}
} }
public void finishFragment() { public void finishFragment() {
@ -188,28 +145,19 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
}); });
} }
private void loadIdentity(UriAttribute linkedId, int certStatus) { private void loadIdentity(LinkedAttribute linkedId, boolean isVerified) {
this.linkedId = linkedId; this.linkedId = linkedId;
if (this.linkedId instanceof LinkedAttribute) { LinkedResource res = ((LinkedAttribute) this.linkedId).mResource;
LinkedResource res = ((LinkedAttribute) this.linkedId).mResource; linkedResource = (LinkedTokenResource) res;
linkedResource = (LinkedTokenResource) res;
}
if (!isSecret) { if (!isSecret) {
switch (certStatus) { if (isVerified) {
case Certs.VERIFIED_SECRET: KeyFormattingUtils.setStatusImage(getContext(), viewHolder.mLinkedIdHolder.vVerified,
KeyFormattingUtils.setStatusImage(getContext(), viewHolder.mLinkedIdHolder.vVerified, null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR); } else {
break; KeyFormattingUtils.setStatusImage(getContext(), viewHolder.mLinkedIdHolder.vVerified,
case Certs.VERIFIED_SELF: null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
KeyFormattingUtils.setStatusImage(getContext(), viewHolder.mLinkedIdHolder.vVerified,
null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
break;
default:
KeyFormattingUtils.setStatusImage(getContext(), viewHolder.mLinkedIdHolder.vVerified,
null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR);
break;
} }
} else { } else {
viewHolder.mLinkedIdHolder.vVerified.setImageResource(R.drawable.octo_link_24dp); viewHolder.mLinkedIdHolder.vVerified.setImageResource(R.drawable.octo_link_24dp);
@ -219,13 +167,6 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
setShowVerifying(false); setShowVerifying(false);
// no resource, nothing further we can do
if (linkedResource == null) {
viewHolder.vButtonView.setVisibility(View.GONE);
viewHolder.vButtonVerify.setVisibility(View.GONE);
return;
}
if (linkedResource.isViewable()) { if (linkedResource.isViewable()) {
viewHolder.vButtonView.setVisibility(View.VISIBLE); viewHolder.vButtonView.setVisibility(View.VISIBLE);
viewHolder.vButtonView.setOnClickListener(v -> { viewHolder.vButtonView.setOnClickListener(v -> {
@ -241,11 +182,6 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
} }
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
static class ViewHolder { static class ViewHolder {
private final View vButtonView; private final View vButtonView;
private final ViewAnimator vVerifyingContainer; private final ViewAnimator vVerifyingContainer;
@ -395,25 +331,29 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.linked_id_view_fragment, null); View root = inflater.inflate(R.layout.linked_id_view_fragment, superContainer, false);
Context context = getContext();
if (context == null) {
throw new NullPointerException();
}
viewHolder = new ViewHolder(root); viewHolder = new ViewHolder(root);
root.setTag(viewHolder); root.setTag(viewHolder);
((ImageView) root.findViewById(R.id.status_icon_verified)) ((ImageView) root.findViewById(R.id.status_icon_verified))
.setColorFilter(ContextCompat.getColor(getContext(), R.color.android_green_light), .setColorFilter(ContextCompat.getColor(context, R.color.android_green_light),
PorterDuff.Mode.SRC_IN); PorterDuff.Mode.SRC_IN);
((ImageView) root.findViewById(R.id.status_icon_invalid)) ((ImageView) root.findViewById(R.id.status_icon_invalid))
.setColorFilter(ContextCompat.getColor(getContext(), R.color.android_red_light), .setColorFilter(ContextCompat.getColor(context, R.color.android_red_light),
PorterDuff.Mode.SRC_IN); PorterDuff.Mode.SRC_IN);
viewHolder.vButtonVerify.setOnClickListener(v -> verifyResource()); viewHolder.vButtonVerify.setOnClickListener(v -> verifyResource());
viewHolder.vButtonRetry.setOnClickListener(v -> verifyResource()); viewHolder.vButtonRetry.setOnClickListener(v -> verifyResource());
viewHolder.vButtonConfirm.setOnClickListener(v -> initiateCertifying()); viewHolder.vButtonConfirm.setOnClickListener(v -> initiateCertifying());
CertificationDao certificationDao = CertificationDao.getInstance(getContext()); CertificationDao certificationDao = CertificationDao.getInstance(context);
LiveData<CertDetails> certDetailsLiveData = new GenericLiveData<>( LiveData<CertDetails> certDetailsLiveData = new GenericLiveData<>(
getContext(), null, () -> certificationDao.getVerifyingCertDetails(masterKeyId, lidRank)); context, null, () -> certificationDao.getVerifyingCertDetails(masterKeyId, lidRank));
certDetailsLiveData.observe(this, this::onLoadCertDetails); certDetailsLiveData.observe(this, this::onLoadCertDetails);
return root; return root;

View file

@ -23,7 +23,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import android.content.ContentResolver; import android.arch.persistence.db.SupportSQLiteDatabase;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -33,63 +33,40 @@ import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.auto.value.AutoValue; import com.google.auto.value.AutoValue;
import com.squareup.sqldelight.SqlDelightQuery;
import org.openintents.openpgp.util.OpenPgpApi; import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.linked.LinkedAttribute; import org.sufficientlysecure.keychain.linked.LinkedAttribute;
import org.sufficientlysecure.keychain.linked.UriAttribute; import org.sufficientlysecure.keychain.linked.UriAttribute;
import org.sufficientlysecure.keychain.model.AutocryptPeer; import org.sufficientlysecure.keychain.model.AutocryptPeer;
import org.sufficientlysecure.keychain.model.UserPacket;
import org.sufficientlysecure.keychain.model.UserPacket.UserAttribute;
import org.sufficientlysecure.keychain.model.UserPacket.UserId;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
import org.sufficientlysecure.keychain.provider.AutocryptPeerDao; import org.sufficientlysecure.keychain.provider.AutocryptPeerDao;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.ui.util.PackageIconGetter; import org.sufficientlysecure.keychain.ui.util.PackageIconGetter;
import timber.log.Timber; import timber.log.Timber;
public class IdentityDao { public class IdentityDao {
private static final String[] USER_PACKETS_PROJECTION = new String[]{ private final SupportSQLiteDatabase db;
UserPackets._ID,
UserPackets.TYPE,
UserPackets.USER_ID,
UserPackets.ATTRIBUTE_DATA,
UserPackets.RANK,
UserPackets.VERIFIED,
UserPackets.IS_PRIMARY,
UserPackets.IS_REVOKED,
UserPackets.NAME,
UserPackets.EMAIL,
UserPackets.COMMENT,
};
private static final int INDEX_ID = 0;
private static final int INDEX_TYPE = 1;
private static final int INDEX_USER_ID = 2;
private static final int INDEX_ATTRIBUTE_DATA = 3;
private static final int INDEX_RANK = 4;
private static final int INDEX_VERIFIED = 5;
private static final int INDEX_IS_PRIMARY = 6;
private static final int INDEX_IS_REVOKED = 7;
private static final int INDEX_NAME = 8;
private static final int INDEX_EMAIL = 9;
private static final int INDEX_COMMENT = 10;
private static final String USER_IDS_WHERE = UserPackets.IS_REVOKED + " = 0";
private final ContentResolver contentResolver;
private final PackageIconGetter packageIconGetter; private final PackageIconGetter packageIconGetter;
private final PackageManager packageManager; private final PackageManager packageManager;
private final AutocryptPeerDao autocryptPeerDao; private final AutocryptPeerDao autocryptPeerDao;
static IdentityDao getInstance(Context context) { public static IdentityDao getInstance(Context context) {
ContentResolver contentResolver = context.getContentResolver(); SupportSQLiteDatabase db = new KeychainDatabase(context).getWritableDatabase();
PackageManager packageManager = context.getPackageManager(); PackageManager packageManager = context.getPackageManager();
PackageIconGetter iconGetter = PackageIconGetter.getInstance(context); PackageIconGetter iconGetter = PackageIconGetter.getInstance(context);
AutocryptPeerDao autocryptPeerDao = AutocryptPeerDao.getInstance(context); AutocryptPeerDao autocryptPeerDao = AutocryptPeerDao.getInstance(context);
return new IdentityDao(contentResolver, packageManager, iconGetter, autocryptPeerDao); return new IdentityDao(db, packageManager, iconGetter, autocryptPeerDao);
} }
private IdentityDao(ContentResolver contentResolver, PackageManager packageManager, PackageIconGetter iconGetter, private IdentityDao(SupportSQLiteDatabase db,
PackageManager packageManager, PackageIconGetter iconGetter,
AutocryptPeerDao autocryptPeerDao) { AutocryptPeerDao autocryptPeerDao) {
this.db = db;
this.packageManager = packageManager; this.packageManager = packageManager;
this.contentResolver = contentResolver;
this.packageIconGetter = iconGetter; this.packageIconGetter = iconGetter;
this.autocryptPeerDao = autocryptPeerDao; this.autocryptPeerDao = autocryptPeerDao;
} }
@ -156,73 +133,70 @@ public class IdentityDao {
} }
private void loadLinkedIds(ArrayList<IdentityInfo> identities, long masterKeyId) { private void loadLinkedIds(ArrayList<IdentityInfo> identities, long masterKeyId) {
Cursor cursor = contentResolver.query(UserPackets.buildLinkedIdsUri(masterKeyId), SqlDelightQuery query = UserPacket.FACTORY.selectUserAttributesByTypeAndMasterKeyId(
USER_PACKETS_PROJECTION, USER_IDS_WHERE, null, null); (long) WrappedUserAttribute.UAT_URI_ATTRIBUTE, masterKeyId);
if (cursor == null) { try (Cursor cursor = db.query(query)) {
Timber.e("Error loading key items!");
return;
}
try {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
int rank = cursor.getInt(INDEX_RANK); UserAttribute userAttribute = UserPacket.USER_ATTRIBUTE_MAPPER.map(cursor);
int verified = cursor.getInt(INDEX_VERIFIED);
boolean isPrimary = cursor.getInt(INDEX_IS_PRIMARY) != 0;
byte[] data = cursor.getBlob(INDEX_ATTRIBUTE_DATA); LinkedIdInfo linkedIdInfo = parseLinkedIdInfo(userAttribute);
try { identities.add(linkedIdInfo);
UriAttribute uriAttribute = LinkedAttribute.fromAttributeData(data);
if (uriAttribute instanceof LinkedAttribute) {
LinkedIdInfo identityInfo = LinkedIdInfo.create(rank, verified, isPrimary, uriAttribute);
identities.add(identityInfo);
}
} catch (IOException e) {
Timber.e(e, "Failed parsing uri attribute");
}
} }
} finally {
cursor.close();
} }
} }
private void loadUserIds(ArrayList<IdentityInfo> identities, long masterKeyId) { public LinkedIdInfo getLinkedIdInfo(long masterKeyId, int rank) {
Cursor cursor = contentResolver.query(UserPackets.buildUserIdsUri(masterKeyId), SqlDelightQuery query = UserPacket.FACTORY.selectSpecificUserAttribute(
USER_PACKETS_PROJECTION, USER_IDS_WHERE, null, null); (long) WrappedUserAttribute.UAT_URI_ATTRIBUTE, masterKeyId, rank);
if (cursor == null) { try (Cursor cursor = db.query(query)) {
Timber.e("Error loading key items!"); if (cursor.moveToFirst()) {
return; UserAttribute userAttribute = UserPacket.USER_ATTRIBUTE_MAPPER.map(cursor);
return parseLinkedIdInfo(userAttribute);
}
} }
return null;
}
@Nullable
private LinkedIdInfo parseLinkedIdInfo(UserAttribute userAttribute) {
try { try {
UriAttribute uriAttribute = LinkedAttribute.fromAttributeData(userAttribute.attribute_data());
if (uriAttribute instanceof LinkedAttribute) {
return LinkedIdInfo.create(userAttribute.rank(),
userAttribute.isVerified(), userAttribute.is_primary(), (LinkedAttribute) uriAttribute);
}
} catch (IOException e) {
Timber.e(e, "Failed parsing uri attribute");
}
return null;
}
private void loadUserIds(ArrayList<IdentityInfo> identities, long masterKeyId) {
SqlDelightQuery query = UserPacket.FACTORY.selectUserIdsByMasterKeyId(masterKeyId);
try (Cursor cursor = db.query(query)) {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
int rank = cursor.getInt(INDEX_RANK); UserId userId = UserPacket.USER_ID_MAPPER.map(cursor);
int verified = cursor.getInt(INDEX_VERIFIED);
boolean isPrimary = cursor.getInt(INDEX_IS_PRIMARY) != 0;
if (!cursor.isNull(INDEX_NAME) || !cursor.isNull(INDEX_EMAIL)) { if (userId.name() != null || userId.email() != null) {
String name = cursor.getString(INDEX_NAME); IdentityInfo identityInfo = UserIdInfo.create(
String email = cursor.getString(INDEX_EMAIL); userId.rank(), userId.isVerified(), userId.is_primary(), userId.name(), userId.email(), userId.comment());
String comment = cursor.getString(INDEX_COMMENT);
IdentityInfo identityInfo = UserIdInfo.create(rank, verified, isPrimary, name, email, comment);
identities.add(identityInfo); identities.add(identityInfo);
} }
} }
} finally {
cursor.close();
} }
} }
public interface IdentityInfo { public interface IdentityInfo {
int getRank(); int getRank();
int getVerified(); boolean isVerified();
boolean isPrimary(); boolean isPrimary();
} }
@AutoValue @AutoValue
public abstract static class UserIdInfo implements IdentityInfo { public abstract static class UserIdInfo implements IdentityInfo {
public abstract int getRank(); public abstract int getRank();
public abstract int getVerified(); public abstract boolean isVerified();
public abstract boolean isPrimary(); public abstract boolean isPrimary();
@Nullable @Nullable
@ -232,29 +206,29 @@ public class IdentityDao {
@Nullable @Nullable
public abstract String getComment(); public abstract String getComment();
static UserIdInfo create(int rank, int verified, boolean isPrimary, String name, String email, static UserIdInfo create(int rank, boolean isVerified, boolean isPrimary, String name, String email,
String comment) { String comment) {
return new AutoValue_IdentityDao_UserIdInfo(rank, verified, isPrimary, name, email, comment); return new AutoValue_IdentityDao_UserIdInfo(rank, isVerified, isPrimary, name, email, comment);
} }
} }
@AutoValue @AutoValue
public abstract static class LinkedIdInfo implements IdentityInfo { public abstract static class LinkedIdInfo implements IdentityInfo {
public abstract int getRank(); public abstract int getRank();
public abstract int getVerified(); public abstract boolean isVerified();
public abstract boolean isPrimary(); public abstract boolean isPrimary();
public abstract UriAttribute getUriAttribute(); public abstract LinkedAttribute getLinkedAttribute();
static LinkedIdInfo create(int rank, int verified, boolean isPrimary, UriAttribute uriAttribute) { static LinkedIdInfo create(int rank, boolean isVerified, boolean isPrimary, LinkedAttribute linkedAttribute) {
return new AutoValue_IdentityDao_LinkedIdInfo(rank, verified, isPrimary, uriAttribute); return new AutoValue_IdentityDao_LinkedIdInfo(rank, isVerified, isPrimary, linkedAttribute);
} }
} }
@AutoValue @AutoValue
public abstract static class AutocryptPeerInfo implements IdentityInfo { public abstract static class AutocryptPeerInfo implements IdentityInfo {
public abstract int getRank(); public abstract int getRank();
public abstract int getVerified(); public abstract boolean isVerified();
public abstract boolean isPrimary(); public abstract boolean isPrimary();
public abstract String getIdentity(); public abstract String getIdentity();
@ -268,13 +242,13 @@ public class IdentityDao {
static AutocryptPeerInfo create(UserIdInfo userIdInfo, String autocryptPeer, String packageName, static AutocryptPeerInfo create(UserIdInfo userIdInfo, String autocryptPeer, String packageName,
Drawable appIcon, Intent autocryptPeerIntent) { Drawable appIcon, Intent autocryptPeerIntent) {
return new AutoValue_IdentityDao_AutocryptPeerInfo(userIdInfo.getRank(), userIdInfo.getVerified(), return new AutoValue_IdentityDao_AutocryptPeerInfo(userIdInfo.getRank(), userIdInfo.isVerified(),
userIdInfo.isPrimary(), autocryptPeer, packageName, appIcon, userIdInfo, autocryptPeerIntent); userIdInfo.isPrimary(), autocryptPeer, packageName, appIcon, userIdInfo, autocryptPeerIntent);
} }
static AutocryptPeerInfo create(String autocryptPeer, String packageName, Drawable appIcon, Intent autocryptPeerIntent) { static AutocryptPeerInfo create(String autocryptPeer, String packageName, Drawable appIcon, Intent autocryptPeerIntent) {
return new AutoValue_IdentityDao_AutocryptPeerInfo( return new AutoValue_IdentityDao_AutocryptPeerInfo(
0, Certs.VERIFIED_SELF, false, autocryptPeer, packageName, appIcon, null, autocryptPeerIntent); 0, false, false, autocryptPeer, packageName, appIcon, null, autocryptPeerIntent);
} }
} }

View file

@ -18,20 +18,17 @@
package org.sufficientlysecure.keychain.ui.keyview.presenter; package org.sufficientlysecure.keychain.ui.keyview.presenter;
import java.io.IOException;
import java.util.List; import java.util.List;
import android.arch.lifecycle.LiveData; import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.Observer; import android.arch.lifecycle.Observer;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.view.View; import android.view.View;
import org.sufficientlysecure.keychain.provider.AutocryptPeerDao; import org.sufficientlysecure.keychain.provider.AutocryptPeerDao;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter; import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter;
import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.IdentityClickListener; import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.IdentityClickListener;
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
@ -114,17 +111,14 @@ public class IdentitiesPresenter implements Observer<List<IdentityInfo>> {
} }
private void showLinkedId(final LinkedIdInfo info) { private void showLinkedId(final LinkedIdInfo info) {
Uri dataUri = UserPackets.buildLinkedIdsUri(KeyRings.buildGenericKeyRingUri(masterKeyId)); LinkedIdViewFragment frag = LinkedIdViewFragment.newInstance(masterKeyId, info.getRank(), isSecret);
LinkedIdViewFragment frag = LinkedIdViewFragment.newInstance(dataUri, info.getRank(), isSecret, masterKeyId);
viewKeyMvpView.switchToFragment(frag, "linked_id"); viewKeyMvpView.switchToFragment(frag, "linked_id");
} }
private void showUserIdInfo(UserIdInfo info) { private void showUserIdInfo(UserIdInfo info) {
if (!isSecret) { if (!isSecret) {
final int isVerified = info.getVerified(); UserIdInfoDialogFragment dialogFragment = UserIdInfoDialogFragment.newInstance(false, info.isVerified());
UserIdInfoDialogFragment dialogFragment = UserIdInfoDialogFragment.newInstance(false, isVerified);
viewKeyMvpView.showDialogFragment(dialogFragment, "userIdInfoDialog"); viewKeyMvpView.showDialogFragment(dialogFragment, "userIdInfoDialog");
} }
} }

View file

@ -727,8 +727,6 @@
<string name="user_id_info_certified_text">"This identity has been confirmed by you."</string> <string name="user_id_info_certified_text">"This identity has been confirmed by you."</string>
<string name="user_id_info_uncertified_title">"Not confirmed"</string> <string name="user_id_info_uncertified_title">"Not confirmed"</string>
<string name="user_id_info_uncertified_text">"This identity has not been confirmed yet. You cannot be sure if the identity really corresponds to a specific person."</string> <string name="user_id_info_uncertified_text">"This identity has not been confirmed yet. You cannot be sure if the identity really corresponds to a specific person."</string>
<string name="user_id_info_invalid_title">"Invalid"</string>
<string name="user_id_info_invalid_text">"Something is wrong with this identity!"</string>
<!-- Key trust --> <!-- Key trust -->
<string name="key_trust_no_cloud_evidence">"No proof from the Internet on this keys trustworthiness."</string> <string name="key_trust_no_cloud_evidence">"No proof from the Internet on this keys trustworthiness."</string>

View file

@ -1,10 +1,12 @@
import java.lang.Integer;
-- TODO implement. this is only here for reference in SQLDelight -- TODO implement. this is only here for reference in SQLDelight
CREATE TABLE IF NOT EXISTS certs( CREATE TABLE IF NOT EXISTS certs(
master_key_id INTEGER NOT NULL, master_key_id INTEGER NOT NULL,
rank INTEGER NOT NULL, rank INTEGER NOT NULL,
key_id_certifier INTEGER NOT NULL, key_id_certifier INTEGER NOT NULL,
type INTEGER NOT NULL, type INTEGER NOT NULL,
verified INTEGER NOT NULL, verified INTEGER AS Integer NOT NULL,
creation INTEGER NOT NULL, creation INTEGER NOT NULL,
data BLOB NOT NULL, data BLOB NOT NULL,
PRIMARY KEY(master_key_id, rank, key_id_certifier), PRIMARY KEY(master_key_id, rank, key_id_certifier),

View file

@ -1,15 +1,35 @@
import java.lang.Integer;
CREATE TABLE IF NOT EXISTS user_packets( CREATE TABLE IF NOT EXISTS user_packets(
master_key_id INTEGER, master_key_id INTEGER NOT NULL,
rank INTEGER AS Integer NOT NULL,
type INTEGER, type INTEGER,
user_id TEXT, user_id TEXT,
name TEXT, name TEXT,
email TEXT, email TEXT,
comment TEXT, comment TEXT,
attribute_data BLOB, attribute_data BLOB,
is_primary INTEGER, is_primary INTEGER AS Boolean NOT NULL,
is_revoked INTEGER, is_revoked INTEGER AS Boolean NOT NULL,
rank INTEGER,
PRIMARY KEY(master_key_id, rank), PRIMARY KEY(master_key_id, rank),
FOREIGN KEY(master_key_id) REFERENCES FOREIGN KEY(master_key_id) REFERENCES
keyrings_public(master_key_id) ON DELETE CASCADE keyrings_public(master_key_id) ON DELETE CASCADE
); );
selectUserIdsByMasterKeyId:
SELECT user_packets.master_key_id, user_packets.rank, user_id, name, email, comment, is_primary, is_revoked, certs.verified
FROM user_packets
LEFT JOIN certs ON ( user_packets.master_key_id = certs.master_key_id AND user_packets.rank = certs.rank AND certs.verified > 0 )
WHERE user_packets.type IS NULL AND user_packets.is_revoked = 0 AND user_packets.master_key_id = ?;
selectUserAttributesByTypeAndMasterKeyId:
SELECT user_packets.master_key_id, user_packets.rank, attribute_data, is_primary, is_revoked, certs.verified
FROM user_packets
LEFT JOIN certs ON ( user_packets.master_key_id = certs.master_key_id AND user_packets.rank = certs.rank AND certs.verified > 0 )
WHERE user_packets.type = ? AND user_packets.is_revoked = 0 AND user_packets.master_key_id = ?;
selectSpecificUserAttribute:
SELECT user_packets.master_key_id, user_packets.rank, attribute_data, is_primary, is_revoked, certs.verified
FROM user_packets
LEFT JOIN certs ON ( user_packets.master_key_id = certs.master_key_id AND user_packets.rank = certs.rank AND certs.verified > 0 )
WHERE user_packets.type = ? AND user_packets.master_key_id = ? AND user_packets.rank = ?;