Introduce allowed keys table per API client

This commit is contained in:
Dominik Schürmann 2015-01-29 17:46:27 +01:00
parent e0369a2f14
commit d6e4936fa5
4 changed files with 70 additions and 5 deletions

View File

@ -85,6 +85,11 @@ public class KeychainContract {
String PACKAGE_NAME = "package_name"; // foreign key to api_apps.package_name String PACKAGE_NAME = "package_name"; // foreign key to api_apps.package_name
} }
interface ApiAppsAllowedKeysColumns {
String KEY_ID = "key_id"; // not a database id
String PACKAGE_NAME = "package_name"; // foreign key to api_apps.package_name
}
public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".provider"; public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".provider";
private static final Uri BASE_CONTENT_URI_INTERNAL = Uri private static final Uri BASE_CONTENT_URI_INTERNAL = Uri
@ -106,6 +111,7 @@ public class KeychainContract {
public static final String BASE_API_APPS = "api_apps"; public static final String BASE_API_APPS = "api_apps";
public static final String PATH_ACCOUNTS = "accounts"; public static final String PATH_ACCOUNTS = "accounts";
public static final String PATH_ALLOWED_KEYS = "allowed_keys";
public static class KeyRings implements BaseColumns, KeysColumns, UserPacketsColumns { public static class KeyRings implements BaseColumns, KeysColumns, UserPacketsColumns {
public static final String MASTER_KEY_ID = KeysColumns.MASTER_KEY_ID; public static final String MASTER_KEY_ID = KeysColumns.MASTER_KEY_ID;
@ -305,6 +311,28 @@ public class KeychainContract {
} }
} }
public static class ApiAllowedKeys implements ApiAppsAllowedKeysColumns, BaseColumns {
public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon()
.appendPath(BASE_API_APPS).build();
/**
* Use if multiple items get returned
*/
public static final String CONTENT_TYPE
= "vnd.android.cursor.dir/vnd.org.sufficientlysecure.keychain.provider.api_apps.allowed_keys";
/**
* Use if a single item is returned
*/
public static final String CONTENT_ITEM_TYPE
= "vnd.android.cursor.item/vnd.org.sufficientlysecure.keychain.provider.api_apps.allowed_keys";
public static Uri buildBaseUri(String packageName) {
return CONTENT_URI.buildUpon().appendEncodedPath(packageName).appendPath(PATH_ALLOWED_KEYS)
.build();
}
}
public static class Certs implements CertsColumns, BaseColumns { public static class Certs implements CertsColumns, BaseColumns {
public static final String USER_ID = UserPacketsColumns.USER_ID; public static final String USER_ID = UserPacketsColumns.USER_ID;
public static final String SIGNER_UID = "signer_user_id"; public static final String SIGNER_UID = "signer_user_id";

View File

@ -28,6 +28,7 @@ import android.provider.BaseColumns;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAllowedKeysColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsAccountsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns;
import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns; import org.sufficientlysecure.keychain.provider.KeychainContract.CertsColumns;
@ -52,7 +53,7 @@ import java.io.IOException;
*/ */
public class KeychainDatabase extends SQLiteOpenHelper { public class KeychainDatabase extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "openkeychain.db"; private static final String DATABASE_NAME = "openkeychain.db";
private static final int DATABASE_VERSION = 7; private static final int DATABASE_VERSION = 8;
static Boolean apgHack = false; static Boolean apgHack = false;
private Context mContext; private Context mContext;
@ -64,6 +65,7 @@ public class KeychainDatabase extends SQLiteOpenHelper {
String CERTS = "certs"; String CERTS = "certs";
String API_APPS = "api_apps"; String API_APPS = "api_apps";
String API_ACCOUNTS = "api_accounts"; String API_ACCOUNTS = "api_accounts";
String API_ALLOWED_KEYS = "api_allowed_keys";
} }
private static final String CREATE_KEYRINGS_PUBLIC = private static final String CREATE_KEYRINGS_PUBLIC =
@ -166,6 +168,17 @@ public class KeychainDatabase extends SQLiteOpenHelper {
+ Tables.API_APPS + "(" + ApiAppsColumns.PACKAGE_NAME + ") ON DELETE CASCADE" + Tables.API_APPS + "(" + ApiAppsColumns.PACKAGE_NAME + ") ON DELETE CASCADE"
+ ")"; + ")";
private static final String CREATE_API_APPS_ALLOWED_KEYS =
"CREATE TABLE IF NOT EXISTS " + Tables.API_ALLOWED_KEYS + " ("
+ BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ ApiAppsAllowedKeysColumns.KEY_ID + " INTEGER, "
+ ApiAppsAllowedKeysColumns.PACKAGE_NAME + " TEXT NOT NULL, "
+ "UNIQUE(" + ApiAppsAllowedKeysColumns.PACKAGE_NAME + "), "
+ "FOREIGN KEY(" + ApiAppsAllowedKeysColumns.PACKAGE_NAME + ") REFERENCES "
+ Tables.API_APPS + "(" + ApiAppsAllowedKeysColumns.PACKAGE_NAME + ") ON DELETE CASCADE"
+ ")";
KeychainDatabase(Context context) { KeychainDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION); super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context; mContext = context;
@ -243,6 +256,15 @@ public class KeychainDatabase extends SQLiteOpenHelper {
case 6: case 6:
db.execSQL("ALTER TABLE user_ids ADD COLUMN type INTEGER"); db.execSQL("ALTER TABLE user_ids ADD COLUMN type INTEGER");
db.execSQL("ALTER TABLE user_ids ADD COLUMN attribute_data BLOB"); db.execSQL("ALTER TABLE user_ids ADD COLUMN attribute_data BLOB");
case 7:
// consolidate
case 8:
// new table for allowed key ids in API
try {
db.execSQL(CREATE_API_APPS_ALLOWED_KEYS);
} catch (Exception e) {
// never mind, the column probably already existed
}
} }
// always do consolidate after upgrade // always do consolidate after upgrade

View File

@ -31,6 +31,7 @@ import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAllowedKeys;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts;
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
@ -63,9 +64,10 @@ public class KeychainProvider extends ContentProvider {
private static final int KEY_RING_CERTS_SPECIFIC = 206; private static final int KEY_RING_CERTS_SPECIFIC = 206;
private static final int API_APPS = 301; private static final int API_APPS = 301;
private static final int API_APPS_BY_PACKAGE_NAME = 303; private static final int API_APPS_BY_PACKAGE_NAME = 302;
private static final int API_ACCOUNTS = 304; private static final int API_ACCOUNTS = 303;
private static final int API_ACCOUNTS_BY_ACCOUNT_NAME = 306; private static final int API_ACCOUNTS_BY_ACCOUNT_NAME = 304;
private static final int API_ALLOWED_KEYS = 305;
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;
@ -162,6 +164,8 @@ public class KeychainProvider extends ContentProvider {
* *
* api_apps/_/accounts * api_apps/_/accounts
* api_apps/_/accounts/_ (account name) * api_apps/_/accounts/_ (account name)
*
* api_apps/_/allowed_keys
* </pre> * </pre>
*/ */
matcher.addURI(authority, KeychainContract.BASE_API_APPS, API_APPS); matcher.addURI(authority, KeychainContract.BASE_API_APPS, API_APPS);
@ -172,6 +176,9 @@ public class KeychainProvider extends ContentProvider {
matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/" matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/"
+ KeychainContract.PATH_ACCOUNTS + "/*", API_ACCOUNTS_BY_ACCOUNT_NAME); + KeychainContract.PATH_ACCOUNTS + "/*", API_ACCOUNTS_BY_ACCOUNT_NAME);
matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/*/"
+ KeychainContract.PATH_ALLOWED_KEYS, API_ALLOWED_KEYS);
return matcher; return matcher;
} }
@ -223,6 +230,9 @@ public class KeychainProvider extends ContentProvider {
case API_ACCOUNTS_BY_ACCOUNT_NAME: case API_ACCOUNTS_BY_ACCOUNT_NAME:
return ApiAccounts.CONTENT_ITEM_TYPE; return ApiAccounts.CONTENT_ITEM_TYPE;
case API_ALLOWED_KEYS:
return ApiAllowedKeys.CONTENT_ITEM_TYPE;
default: default:
throw new UnsupportedOperationException("Unknown uri: " + uri); throw new UnsupportedOperationException("Unknown uri: " + uri);
} }
@ -613,6 +623,12 @@ public class KeychainProvider extends ContentProvider {
qb.appendWhere(" AND " + Tables.API_ACCOUNTS + "." + ApiAccounts.ACCOUNT_NAME + " = "); qb.appendWhere(" AND " + Tables.API_ACCOUNTS + "." + ApiAccounts.ACCOUNT_NAME + " = ");
qb.appendWhereEscapeString(uri.getLastPathSegment()); qb.appendWhereEscapeString(uri.getLastPathSegment());
break;
case API_ALLOWED_KEYS:
qb.setTables(Tables.API_ALLOWED_KEYS);
qb.appendWhere(Tables.API_ALLOWED_KEYS + "." + ApiAccounts.PACKAGE_NAME + " = ");
qb.appendWhereEscapeString(uri.getPathSegments().get(1));
break; break;
default: default:
throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")"); throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")");

View File

@ -58,7 +58,6 @@ public class AccountSettingsActivity extends BaseActivity {
} }
}); });
mAccountSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById( mAccountSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById(
R.id.api_account_settings_fragment); R.id.api_account_settings_fragment);