Refactored Core Database.

This commit is contained in:
Neil Marietta 2021-07-12 10:04:33 +02:00
parent 2a4929a4ad
commit 63cb162e19
53 changed files with 5520 additions and 246 deletions

View File

@ -24,7 +24,7 @@ plugins {
kotlin("android")
}
libVersion = Version(1, 1, 8)
libVersion = Version(1, 3, 1)
android()

View File

@ -27,7 +27,7 @@ plugins {
id("dagger.hilt.android.plugin")
}
libVersion = Version(1, 1, 8)
libVersion = Version(1, 3, 1)
android()

View File

@ -25,6 +25,7 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import me.proton.core.account.data.db.AccountDatabase
import me.proton.core.account.data.repository.AccountRepositoryImpl
import me.proton.core.account.domain.repository.AccountRepository
import me.proton.core.accountmanager.data.AccountManagerImpl
@ -71,10 +72,10 @@ object AccountManagerModule {
@Singleton
fun provideAccountRepository(
product: Product,
accountManagerDatabase: AccountManagerDatabase,
db: AccountDatabase,
keyStoreCrypto: KeyStoreCrypto
): AccountRepository =
AccountRepositoryImpl(product, accountManagerDatabase, keyStoreCrypto)
AccountRepositoryImpl(product, db, keyStoreCrypto)
@Provides
@Singleton

View File

@ -25,7 +25,7 @@ plugins {
kotlin("kapt")
}
libVersion = Version(1, 1, 8)
libVersion = Version(1, 3, 1)
android() {
defaultConfig {

View File

@ -19,23 +19,16 @@
package me.proton.core.accountmanager.data.db
import android.content.Context
import androidx.room.AutoMigration
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.withTransaction
import me.proton.core.account.data.db.AccountConverters
import me.proton.core.account.data.db.AccountDatabase
import me.proton.core.account.data.entity.AccountEntity
import me.proton.core.account.data.entity.AccountMetadataEntity
import me.proton.core.account.data.entity.SessionDetailsEntity
import me.proton.core.account.data.entity.SessionEntity
import me.proton.core.accountmanager.data.db.migration.MIGRATION_1_2
import me.proton.core.accountmanager.data.db.migration.MIGRATION_2_3
import me.proton.core.accountmanager.data.db.migration.MIGRATION_3_4
import me.proton.core.accountmanager.data.db.migration.MIGRATION_4_5
import me.proton.core.crypto.android.keystore.CryptoConverters
import me.proton.core.data.db.BaseDatabase
import me.proton.core.data.db.CommonConverters
import me.proton.core.humanverification.data.db.HumanVerificationConverters
import me.proton.core.humanverification.data.db.HumanVerificationDatabase
@ -76,11 +69,7 @@ import me.proton.core.user.data.entity.UserKeyEntity
// mail-settings
MailSettingsEntity::class
],
autoMigrations = [
AutoMigration(from = 4, to = 5, spec = MIGRATION_4_5::class),
AutoMigration(from = 5, to = 6)
],
version = 6,
version = AccountManagerDatabase.version,
exportSchema = true
)
@TypeConverters(
@ -91,7 +80,7 @@ import me.proton.core.user.data.entity.UserKeyEntity
HumanVerificationConverters::class
)
abstract class AccountManagerDatabase :
RoomDatabase(),
BaseDatabase(),
AccountDatabase,
UserDatabase,
AddressDatabase,
@ -100,16 +89,24 @@ abstract class AccountManagerDatabase :
PublicAddressDatabase,
MailSettingsDatabase {
override suspend fun <R> inTransaction(block: suspend () -> R): R = withTransaction(block)
companion object {
fun buildDatabase(context: Context): AccountManagerDatabase {
return Room
.databaseBuilder(context, AccountManagerDatabase::class.java, "db-account-manager")
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_2_3)
.addMigrations(MIGRATION_3_4)
const val name = "db-account-manager"
const val version = 6
val migrations = listOf(
AccountManagerDatabaseMigrations.MIGRATION_1_2,
AccountManagerDatabaseMigrations.MIGRATION_2_3,
AccountManagerDatabaseMigrations.MIGRATION_3_4,
AccountManagerDatabaseMigrations.MIGRATION_4_5,
AccountManagerDatabaseMigrations.MIGRATION_5_6,
)
fun databaseBuilder(context: Context): Builder<AccountManagerDatabase> =
databaseBuilder<AccountManagerDatabase>(context, name)
.apply { migrations.forEach { addMigrations(it) } }
fun buildDatabase(context: Context): AccountManagerDatabase =
databaseBuilder(context)
.build()
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2020 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.accountmanager.data.db
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.account.data.db.AccountDatabase
import me.proton.core.humanverification.data.db.HumanVerificationDatabase
import me.proton.core.key.data.db.KeySaltDatabase
import me.proton.core.key.data.db.PublicAddressDatabase
import me.proton.core.mailsettings.data.db.MailSettingsDatabase
import me.proton.core.user.data.db.AddressDatabase
import me.proton.core.user.data.db.UserDatabase
object AccountManagerDatabaseMigrations {
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
AccountDatabase.MIGRATION_1.migrate(database)
}
}
val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
AccountDatabase.MIGRATION_2.migrate(database)
UserDatabase.MIGRATION_0.migrate(database)
AddressDatabase.MIGRATION_0.migrate(database)
KeySaltDatabase.MIGRATION_0.migrate(database)
PublicAddressDatabase.MIGRATION_0.migrate(database)
}
}
val MIGRATION_3_4 = object : Migration(3, 4) {
override fun migrate(database: SupportSQLiteDatabase) {
AddressDatabase.MIGRATION_1.migrate(database)
}
}
val MIGRATION_4_5 = object : Migration(4, 5) {
override fun migrate(database: SupportSQLiteDatabase) {
AccountDatabase.MIGRATION_3.migrate(database)
HumanVerificationDatabase.MIGRATION_0.migrate(database)
}
}
val MIGRATION_5_6 = object : Migration(5, 6) {
override fun migrate(database: SupportSQLiteDatabase) {
MailSettingsDatabase.MIGRATION_0.migrate(database)
}
}
}

View File

@ -1,83 +0,0 @@
/*
* Copyright (c) 2020 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.accountmanager.data.db.migration
import androidx.room.DeleteColumn
import androidx.room.DeleteTable
import androidx.room.migration.AutoMigrationSpec
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
internal val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
// Added Table HumanVerificationDetailsEntity
database.execSQL("CREATE TABLE IF NOT EXISTS `HumanVerificationDetailsEntity` (`sessionId` TEXT NOT NULL, `verificationMethods` TEXT NOT NULL, `captchaVerificationToken` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_HumanVerificationDetailsEntity_sessionId` ON `HumanVerificationDetailsEntity` (`sessionId`)")
}
}
internal val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
// Added Table SessionDetailsEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `SessionDetailsEntity` (`sessionId` TEXT NOT NULL, `initialEventId` TEXT NOT NULL, `requiredAccountType` TEXT NOT NULL, `secondFactorEnabled` INTEGER NOT NULL, `twoPassModeEnabled` INTEGER NOT NULL, `password` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_SessionDetailsEntity_sessionId` ON `SessionDetailsEntity` (`sessionId`)")
// Added Table UserEntity, UserKeyEntity, AddressEntity, AddressKeyEntity, KeySaltEntity, PublicAddressEntity, PublicAddressKeyEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `UserEntity` (`userId` TEXT NOT NULL, `email` TEXT, `name` TEXT, `displayName` TEXT, `currency` TEXT NOT NULL, `credit` INTEGER NOT NULL, `usedSpace` INTEGER NOT NULL, `maxSpace` INTEGER NOT NULL, `maxUpload` INTEGER NOT NULL, `role` INTEGER, `private` INTEGER NOT NULL, `subscribed` INTEGER NOT NULL, `services` INTEGER NOT NULL, `delinquent` INTEGER, `passphrase` BLOB, PRIMARY KEY(`userId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_UserEntity_userId` ON `UserEntity` (`userId`)")
database.execSQL("CREATE TABLE IF NOT EXISTS `UserKeyEntity` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `fingerprint` TEXT, `activation` TEXT, PRIMARY KEY(`keyId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_userId` ON `UserKeyEntity` (`userId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_keyId` ON `UserKeyEntity` (`keyId`)")
database.execSQL("CREATE TABLE IF NOT EXISTS `AddressEntity` (`userId` TEXT NOT NULL, `addressId` TEXT NOT NULL, `email` TEXT NOT NULL, `displayName` TEXT, `domainId` TEXT, `canSend` INTEGER NOT NULL, `canReceive` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `type` INTEGER, `order` INTEGER NOT NULL, PRIMARY KEY(`addressId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AddressEntity_addressId` ON `AddressEntity` (`addressId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AddressEntity_userId` ON `AddressEntity` (`userId`)")
database.execSQL("CREATE TABLE IF NOT EXISTS `AddressKeyEntity` (`addressId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `flags` INTEGER NOT NULL, `token` TEXT, `signature` TEXT, `fingerprint` TEXT, `fingerprints` TEXT, `activation` TEXT, `active` INTEGER NOT NULL, PRIMARY KEY(`keyId`), FOREIGN KEY(`addressId`) REFERENCES `AddressEntity`(`addressId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_addressId` ON `AddressKeyEntity` (`addressId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_keyId` ON `AddressKeyEntity` (`keyId`)")
database.execSQL("CREATE TABLE IF NOT EXISTS `KeySaltEntity` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `keySalt` TEXT, PRIMARY KEY(`userId`, `keyId`))")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_userId` ON `KeySaltEntity` (`userId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_keyId` ON `KeySaltEntity` (`keyId`)")
database.execSQL("CREATE TABLE IF NOT EXISTS `PublicAddressEntity` (`email` TEXT NOT NULL, `recipientType` INTEGER NOT NULL, `mimeType` TEXT, PRIMARY KEY(`email`))")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_PublicAddressEntity_email` ON `PublicAddressEntity` (`email`)")
database.execSQL("CREATE TABLE IF NOT EXISTS `PublicAddressKeyEntity` (`email` TEXT NOT NULL, `flags` INTEGER NOT NULL, `publicKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, PRIMARY KEY(`email`, `publicKey`), FOREIGN KEY(`email`) REFERENCES `PublicAddressEntity`(`email`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_PublicAddressKeyEntity_email` ON `PublicAddressKeyEntity` (`email`)")
}
}
internal val MIGRATION_3_4 = object : Migration(3, 4) {
override fun migrate(database: SupportSQLiteDatabase) {
database.addTableColumn(table = "AddressEntity", column = "signature", type = "TEXT")
}
}
@Suppress("ClassName")
@DeleteColumn.Entries(
value = [
DeleteColumn(tableName = "SessionEntity", columnName = "humanHeaderTokenCode"),
DeleteColumn(tableName = "SessionEntity", columnName = "humanHeaderTokenType"),
]
)
@DeleteTable(tableName = "HumanVerificationDetailsEntity")
internal class MIGRATION_4_5 : AutoMigrationSpec

View File

@ -23,7 +23,7 @@ plugins {
kotlin("jvm")
}
libVersion = Version(1, 1, 8)
libVersion = Version(1, 3, 1)
dependencies {

View File

@ -27,7 +27,7 @@ plugins {
id("dagger.hilt.android.plugin")
}
libVersion = Version(1, 1, 8)
libVersion = Version(1, 3, 1)
android(
useDataBinding = true

View File

@ -24,7 +24,7 @@ plugins {
kotlin("android")
}
libVersion = Version(1, 1, 7)
libVersion = Version(1, 3, 1)
android()

View File

@ -23,7 +23,7 @@ plugins {
kotlin("android")
}
libVersion = Version(1, 1, 7)
libVersion = Version(1, 3, 1)
android()

View File

@ -18,11 +18,85 @@
package me.proton.core.account.data.db
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.data.db.Database
import me.proton.core.data.db.extension.dropTable
import me.proton.core.data.db.extension.dropTableColumn
import me.proton.core.data.db.migration.DatabaseMigration
interface AccountDatabase : Database {
fun accountDao(): AccountDao
fun sessionDao(): SessionDao
fun accountMetadataDao(): AccountMetadataDao
fun sessionDetailsDao(): SessionDetailsDao
companion object {
/**
* - Create Table AccountEntity.
* - Create Table AccountMetadataEntity.
* - Create Table SessionEntity.
*/
val MIGRATION_0 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Create Table AccountEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `AccountEntity` (`userId` TEXT NOT NULL, `username` TEXT NOT NULL, `email` TEXT, `state` TEXT NOT NULL, `sessionId` TEXT, `sessionState` TEXT, PRIMARY KEY(`userId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE NO ACTION )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AccountEntity_sessionId` ON `AccountEntity` (`sessionId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AccountEntity_userId` ON `AccountEntity` (`userId`)")
// Create Table AccountMetadataEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `AccountMetadataEntity` (`userId` TEXT NOT NULL, `product` TEXT NOT NULL, `primaryAtUtc` INTEGER NOT NULL, PRIMARY KEY(`userId`, `product`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_userId` ON `AccountMetadataEntity` (`userId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_product` ON `AccountMetadataEntity` (`product`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_primaryAtUtc` ON `AccountMetadataEntity` (`primaryAtUtc`)")
// Create Table SessionEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `SessionEntity` (`userId` TEXT NOT NULL, `sessionId` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `refreshToken` TEXT NOT NULL, `humanHeaderTokenType` TEXT, `humanHeaderTokenCode` TEXT, `scopes` TEXT NOT NULL, `product` TEXT NOT NULL, PRIMARY KEY(`sessionId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_SessionEntity_sessionId` ON `SessionEntity` (`sessionId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_SessionEntity_userId` ON `SessionEntity` (`userId`)")
}
}
/**
* - Added Table HumanVerificationDetailsEntity.
*/
val MIGRATION_1 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Added Table HumanVerificationDetailsEntity
database.execSQL("CREATE TABLE IF NOT EXISTS `HumanVerificationDetailsEntity` (`sessionId` TEXT NOT NULL, `verificationMethods` TEXT NOT NULL, `captchaVerificationToken` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_HumanVerificationDetailsEntity_sessionId` ON `HumanVerificationDetailsEntity` (`sessionId`)")
}
}
/**
* - Added Table SessionDetailsEntity.
*/
val MIGRATION_2 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Added Table SessionDetailsEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `SessionDetailsEntity` (`sessionId` TEXT NOT NULL, `initialEventId` TEXT NOT NULL, `requiredAccountType` TEXT NOT NULL, `secondFactorEnabled` INTEGER NOT NULL, `twoPassModeEnabled` INTEGER NOT NULL, `password` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_SessionDetailsEntity_sessionId` ON `SessionDetailsEntity` (`sessionId`)")
}
}
/**
* - Drop columns SessionEntity humanHeaderTokenCode & humanHeaderTokenType.
* - Drop Table HumanVerificationDetailsEntity.
*/
val MIGRATION_3 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Drop columns humanHeaderTokenCode & humanHeaderTokenType.
database.dropTableColumn(
table = "SessionEntity",
createTable = {
execSQL("CREATE TABLE IF NOT EXISTS `SessionEntity` (`userId` TEXT NOT NULL, `sessionId` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `refreshToken` TEXT NOT NULL, `scopes` TEXT NOT NULL, `product` TEXT NOT NULL, PRIMARY KEY(`sessionId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
},
createIndices = {
execSQL("CREATE INDEX IF NOT EXISTS `index_SessionEntity_sessionId` ON `SessionEntity` (`sessionId`)")
execSQL("CREATE INDEX IF NOT EXISTS `index_SessionEntity_userId` ON `SessionEntity` (`userId`)")
},
columns = listOf("humanHeaderTokenCode", "humanHeaderTokenType")
)
// Drop Table HumanVerificationDetailsEntity.
database.dropTable(table = "HumanVerificationDetailsEntity")
}
}
}
}

View File

@ -23,7 +23,7 @@ plugins {
kotlin("jvm")
}
libVersion = Version(1, 1, 7)
libVersion = Version(1, 3, 1)
dependencies {

View File

@ -33,6 +33,13 @@ android(
{
defaultConfig {
buildConfigField("String", "ENVIRONMENT", "\"api.proton.black\"")
javaCompileOptions {
annotationProcessorOptions {
arguments["room.schemaLocation"] = "$projectDir/schemas"
// arguments["room.incremental"] = "true"
}
}
}
}
@ -80,13 +87,15 @@ dependencies {
`android-work-runtime`,
// Other
`room-ktx`,
`retrofit`,
`timber`
)
kapt(
`hilt-android-compiler`,
`hilt-androidx-compiler`
`hilt-androidx-compiler`,
`room-compiler`
)
// Test
@ -94,5 +103,5 @@ dependencies {
androidTestImplementation(project(Module.androidInstrumentedTest))
// Lint - off temporary
// lintChecks(project(Module.lint))
// lintChecks(project(Module.lint))
}

View File

@ -0,0 +1,313 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "92feef0ef52ecf835fb3370cf51cc4c9",
"entities": [
{
"tableName": "AccountEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `username` TEXT NOT NULL, `email` TEXT, `state` TEXT NOT NULL, `sessionId` TEXT, `sessionState` TEXT, PRIMARY KEY(`userId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "state",
"columnName": "state",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "sessionState",
"columnName": "sessionState",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_AccountEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "AccountMetadataEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `product` TEXT NOT NULL, `primaryAtUtc` INTEGER NOT NULL, PRIMARY KEY(`userId`, `product`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "primaryAtUtc",
"columnName": "primaryAtUtc",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"userId",
"product"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountMetadataEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_AccountMetadataEntity_product",
"unique": false,
"columnNames": [
"product"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_product` ON `${TABLE_NAME}` (`product`)"
},
{
"name": "index_AccountMetadataEntity_primaryAtUtc",
"unique": false,
"columnNames": [
"primaryAtUtc"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_primaryAtUtc` ON `${TABLE_NAME}` (`primaryAtUtc`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "SessionEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `sessionId` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `refreshToken` TEXT NOT NULL, `humanHeaderTokenType` TEXT, `humanHeaderTokenCode` TEXT, `scopes` TEXT NOT NULL, `product` TEXT NOT NULL, PRIMARY KEY(`sessionId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "accessToken",
"columnName": "accessToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "refreshToken",
"columnName": "refreshToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "humanHeaderTokenType",
"columnName": "humanHeaderTokenType",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "humanHeaderTokenCode",
"columnName": "humanHeaderTokenCode",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "scopes",
"columnName": "scopes",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_SessionEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_SessionEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "HumanVerificationDetailsEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sessionId` TEXT NOT NULL, `verificationMethods` TEXT NOT NULL, `captchaVerificationToken` TEXT, `completed` INTEGER NOT NULL, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "verificationMethods",
"columnName": "verificationMethods",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "captchaVerificationToken",
"columnName": "captchaVerificationToken",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "completed",
"columnName": "completed",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_HumanVerificationDetailsEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_HumanVerificationDetailsEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '92feef0ef52ecf835fb3370cf51cc4c9')"
]
}
}

View File

@ -0,0 +1,307 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "38065983ec98a313c4435c3cf9036636",
"entities": [
{
"tableName": "AccountEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `username` TEXT NOT NULL, `email` TEXT, `state` TEXT NOT NULL, `sessionId` TEXT, `sessionState` TEXT, PRIMARY KEY(`userId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "state",
"columnName": "state",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "sessionState",
"columnName": "sessionState",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_AccountEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "AccountMetadataEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `product` TEXT NOT NULL, `primaryAtUtc` INTEGER NOT NULL, PRIMARY KEY(`userId`, `product`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "primaryAtUtc",
"columnName": "primaryAtUtc",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"userId",
"product"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountMetadataEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_AccountMetadataEntity_product",
"unique": false,
"columnNames": [
"product"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_product` ON `${TABLE_NAME}` (`product`)"
},
{
"name": "index_AccountMetadataEntity_primaryAtUtc",
"unique": false,
"columnNames": [
"primaryAtUtc"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_primaryAtUtc` ON `${TABLE_NAME}` (`primaryAtUtc`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "SessionEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `sessionId` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `refreshToken` TEXT NOT NULL, `humanHeaderTokenType` TEXT, `humanHeaderTokenCode` TEXT, `scopes` TEXT NOT NULL, `product` TEXT NOT NULL, PRIMARY KEY(`sessionId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "accessToken",
"columnName": "accessToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "refreshToken",
"columnName": "refreshToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "humanHeaderTokenType",
"columnName": "humanHeaderTokenType",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "humanHeaderTokenCode",
"columnName": "humanHeaderTokenCode",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "scopes",
"columnName": "scopes",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_SessionEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_SessionEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "HumanVerificationDetailsEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sessionId` TEXT NOT NULL, `verificationMethods` TEXT NOT NULL, `captchaVerificationToken` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "verificationMethods",
"columnName": "verificationMethods",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "captchaVerificationToken",
"columnName": "captchaVerificationToken",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_HumanVerificationDetailsEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_HumanVerificationDetailsEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '38065983ec98a313c4435c3cf9036636')"
]
}
}

View File

@ -0,0 +1,957 @@
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "8cb06731a76441991101263a47393bfe",
"entities": [
{
"tableName": "AccountEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `username` TEXT NOT NULL, `email` TEXT, `state` TEXT NOT NULL, `sessionId` TEXT, `sessionState` TEXT, PRIMARY KEY(`userId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "state",
"columnName": "state",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "sessionState",
"columnName": "sessionState",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_AccountEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "AccountMetadataEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `product` TEXT NOT NULL, `primaryAtUtc` INTEGER NOT NULL, PRIMARY KEY(`userId`, `product`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "primaryAtUtc",
"columnName": "primaryAtUtc",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"userId",
"product"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountMetadataEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_AccountMetadataEntity_product",
"unique": false,
"columnNames": [
"product"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_product` ON `${TABLE_NAME}` (`product`)"
},
{
"name": "index_AccountMetadataEntity_primaryAtUtc",
"unique": false,
"columnNames": [
"primaryAtUtc"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_primaryAtUtc` ON `${TABLE_NAME}` (`primaryAtUtc`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "HumanVerificationDetailsEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sessionId` TEXT NOT NULL, `verificationMethods` TEXT NOT NULL, `captchaVerificationToken` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "verificationMethods",
"columnName": "verificationMethods",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "captchaVerificationToken",
"columnName": "captchaVerificationToken",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_HumanVerificationDetailsEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_HumanVerificationDetailsEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "SessionEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `sessionId` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `refreshToken` TEXT NOT NULL, `humanHeaderTokenType` TEXT, `humanHeaderTokenCode` TEXT, `scopes` TEXT NOT NULL, `product` TEXT NOT NULL, PRIMARY KEY(`sessionId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "accessToken",
"columnName": "accessToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "refreshToken",
"columnName": "refreshToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "humanHeaderTokenType",
"columnName": "humanHeaderTokenType",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "humanHeaderTokenCode",
"columnName": "humanHeaderTokenCode",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "scopes",
"columnName": "scopes",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_SessionEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_SessionEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "SessionDetailsEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sessionId` TEXT NOT NULL, `initialEventId` TEXT NOT NULL, `requiredAccountType` TEXT NOT NULL, `secondFactorEnabled` INTEGER NOT NULL, `twoPassModeEnabled` INTEGER NOT NULL, `password` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "initialEventId",
"columnName": "initialEventId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "requiredAccountType",
"columnName": "requiredAccountType",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "secondFactorEnabled",
"columnName": "secondFactorEnabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "twoPassModeEnabled",
"columnName": "twoPassModeEnabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_SessionDetailsEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionDetailsEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "UserEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `email` TEXT, `name` TEXT, `displayName` TEXT, `currency` TEXT NOT NULL, `credit` INTEGER NOT NULL, `usedSpace` INTEGER NOT NULL, `maxSpace` INTEGER NOT NULL, `maxUpload` INTEGER NOT NULL, `role` INTEGER, `private` INTEGER NOT NULL, `subscribed` INTEGER NOT NULL, `services` INTEGER NOT NULL, `delinquent` INTEGER, `passphrase` BLOB, PRIMARY KEY(`userId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "displayName",
"columnName": "displayName",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "currency",
"columnName": "currency",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "credit",
"columnName": "credit",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "usedSpace",
"columnName": "usedSpace",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "maxSpace",
"columnName": "maxSpace",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "maxUpload",
"columnName": "maxUpload",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "role",
"columnName": "role",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "private",
"columnName": "private",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "subscribed",
"columnName": "subscribed",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "services",
"columnName": "services",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "delinquent",
"columnName": "delinquent",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "passphrase",
"columnName": "passphrase",
"affinity": "BLOB",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_UserEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_UserEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "UserKeyEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `fingerprint` TEXT, `activation` TEXT, PRIMARY KEY(`keyId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyId",
"columnName": "keyId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "privateKey",
"columnName": "privateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isPrimary",
"columnName": "isPrimary",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "fingerprint",
"columnName": "fingerprint",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "activation",
"columnName": "activation",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"keyId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_UserKeyEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_UserKeyEntity_keyId",
"unique": false,
"columnNames": [
"keyId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_keyId` ON `${TABLE_NAME}` (`keyId`)"
}
],
"foreignKeys": [
{
"table": "UserEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "AddressEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `addressId` TEXT NOT NULL, `email` TEXT NOT NULL, `displayName` TEXT, `domainId` TEXT, `canSend` INTEGER NOT NULL, `canReceive` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `type` INTEGER, `order` INTEGER NOT NULL, PRIMARY KEY(`addressId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "addressId",
"columnName": "addressId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "displayName",
"columnName": "displayName",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "domainId",
"columnName": "domainId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "canSend",
"columnName": "canSend",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "canReceive",
"columnName": "canReceive",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "enabled",
"columnName": "enabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "order",
"columnName": "order",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"addressId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AddressEntity_addressId",
"unique": false,
"columnNames": [
"addressId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressEntity_addressId` ON `${TABLE_NAME}` (`addressId`)"
},
{
"name": "index_AddressEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "UserEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "AddressKeyEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`addressId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `flags` INTEGER NOT NULL, `token` TEXT, `signature` TEXT, `fingerprint` TEXT, `fingerprints` TEXT, `activation` TEXT, `active` INTEGER NOT NULL, PRIMARY KEY(`keyId`), FOREIGN KEY(`addressId`) REFERENCES `AddressEntity`(`addressId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "addressId",
"columnName": "addressId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyId",
"columnName": "keyId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "privateKey",
"columnName": "privateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isPrimary",
"columnName": "isPrimary",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "flags",
"columnName": "flags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "token",
"columnName": "token",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "signature",
"columnName": "signature",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "fingerprint",
"columnName": "fingerprint",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "fingerprints",
"columnName": "fingerprints",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "activation",
"columnName": "activation",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "active",
"columnName": "active",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"keyId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AddressKeyEntity_addressId",
"unique": false,
"columnNames": [
"addressId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_addressId` ON `${TABLE_NAME}` (`addressId`)"
},
{
"name": "index_AddressKeyEntity_keyId",
"unique": false,
"columnNames": [
"keyId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_keyId` ON `${TABLE_NAME}` (`keyId`)"
}
],
"foreignKeys": [
{
"table": "AddressEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"addressId"
],
"referencedColumns": [
"addressId"
]
}
]
},
{
"tableName": "KeySaltEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `keySalt` TEXT, PRIMARY KEY(`userId`, `keyId`))",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyId",
"columnName": "keyId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keySalt",
"columnName": "keySalt",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId",
"keyId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_KeySaltEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_KeySaltEntity_keyId",
"unique": false,
"columnNames": [
"keyId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_keyId` ON `${TABLE_NAME}` (`keyId`)"
}
],
"foreignKeys": []
},
{
"tableName": "PublicAddressEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `recipientType` INTEGER NOT NULL, `mimeType` TEXT, PRIMARY KEY(`email`))",
"fields": [
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "recipientType",
"columnName": "recipientType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "mimeType",
"columnName": "mimeType",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"email"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_PublicAddressEntity_email",
"unique": false,
"columnNames": [
"email"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_PublicAddressEntity_email` ON `${TABLE_NAME}` (`email`)"
}
],
"foreignKeys": []
},
{
"tableName": "PublicAddressKeyEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `flags` INTEGER NOT NULL, `publicKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, PRIMARY KEY(`email`, `publicKey`), FOREIGN KEY(`email`) REFERENCES `PublicAddressEntity`(`email`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "flags",
"columnName": "flags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "publicKey",
"columnName": "publicKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isPrimary",
"columnName": "isPrimary",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"email",
"publicKey"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_PublicAddressKeyEntity_email",
"unique": false,
"columnNames": [
"email"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_PublicAddressKeyEntity_email` ON `${TABLE_NAME}` (`email`)"
}
],
"foreignKeys": [
{
"table": "PublicAddressEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"email"
],
"referencedColumns": [
"email"
]
}
]
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8cb06731a76441991101263a47393bfe')"
]
}
}

View File

@ -0,0 +1,963 @@
{
"formatVersion": 1,
"database": {
"version": 4,
"identityHash": "f043b799940e4857395390ed2057c07c",
"entities": [
{
"tableName": "AccountEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `username` TEXT NOT NULL, `email` TEXT, `state` TEXT NOT NULL, `sessionId` TEXT, `sessionState` TEXT, PRIMARY KEY(`userId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "state",
"columnName": "state",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "sessionState",
"columnName": "sessionState",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_AccountEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "AccountMetadataEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `product` TEXT NOT NULL, `primaryAtUtc` INTEGER NOT NULL, PRIMARY KEY(`userId`, `product`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "primaryAtUtc",
"columnName": "primaryAtUtc",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"userId",
"product"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountMetadataEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_AccountMetadataEntity_product",
"unique": false,
"columnNames": [
"product"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_product` ON `${TABLE_NAME}` (`product`)"
},
{
"name": "index_AccountMetadataEntity_primaryAtUtc",
"unique": false,
"columnNames": [
"primaryAtUtc"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_primaryAtUtc` ON `${TABLE_NAME}` (`primaryAtUtc`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "HumanVerificationDetailsEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sessionId` TEXT NOT NULL, `verificationMethods` TEXT NOT NULL, `captchaVerificationToken` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "verificationMethods",
"columnName": "verificationMethods",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "captchaVerificationToken",
"columnName": "captchaVerificationToken",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_HumanVerificationDetailsEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_HumanVerificationDetailsEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "SessionEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `sessionId` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `refreshToken` TEXT NOT NULL, `humanHeaderTokenType` TEXT, `humanHeaderTokenCode` TEXT, `scopes` TEXT NOT NULL, `product` TEXT NOT NULL, PRIMARY KEY(`sessionId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "accessToken",
"columnName": "accessToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "refreshToken",
"columnName": "refreshToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "humanHeaderTokenType",
"columnName": "humanHeaderTokenType",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "humanHeaderTokenCode",
"columnName": "humanHeaderTokenCode",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "scopes",
"columnName": "scopes",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_SessionEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_SessionEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "SessionDetailsEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sessionId` TEXT NOT NULL, `initialEventId` TEXT NOT NULL, `requiredAccountType` TEXT NOT NULL, `secondFactorEnabled` INTEGER NOT NULL, `twoPassModeEnabled` INTEGER NOT NULL, `password` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "initialEventId",
"columnName": "initialEventId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "requiredAccountType",
"columnName": "requiredAccountType",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "secondFactorEnabled",
"columnName": "secondFactorEnabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "twoPassModeEnabled",
"columnName": "twoPassModeEnabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_SessionDetailsEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionDetailsEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "UserEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `email` TEXT, `name` TEXT, `displayName` TEXT, `currency` TEXT NOT NULL, `credit` INTEGER NOT NULL, `usedSpace` INTEGER NOT NULL, `maxSpace` INTEGER NOT NULL, `maxUpload` INTEGER NOT NULL, `role` INTEGER, `private` INTEGER NOT NULL, `subscribed` INTEGER NOT NULL, `services` INTEGER NOT NULL, `delinquent` INTEGER, `passphrase` BLOB, PRIMARY KEY(`userId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "displayName",
"columnName": "displayName",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "currency",
"columnName": "currency",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "credit",
"columnName": "credit",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "usedSpace",
"columnName": "usedSpace",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "maxSpace",
"columnName": "maxSpace",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "maxUpload",
"columnName": "maxUpload",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "role",
"columnName": "role",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "private",
"columnName": "private",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "subscribed",
"columnName": "subscribed",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "services",
"columnName": "services",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "delinquent",
"columnName": "delinquent",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "passphrase",
"columnName": "passphrase",
"affinity": "BLOB",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_UserEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_UserEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "UserKeyEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `fingerprint` TEXT, `activation` TEXT, PRIMARY KEY(`keyId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyId",
"columnName": "keyId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "privateKey",
"columnName": "privateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isPrimary",
"columnName": "isPrimary",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "fingerprint",
"columnName": "fingerprint",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "activation",
"columnName": "activation",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"keyId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_UserKeyEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_UserKeyEntity_keyId",
"unique": false,
"columnNames": [
"keyId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_keyId` ON `${TABLE_NAME}` (`keyId`)"
}
],
"foreignKeys": [
{
"table": "UserEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "AddressEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `addressId` TEXT NOT NULL, `email` TEXT NOT NULL, `displayName` TEXT, `signature` TEXT, `domainId` TEXT, `canSend` INTEGER NOT NULL, `canReceive` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `type` INTEGER, `order` INTEGER NOT NULL, PRIMARY KEY(`addressId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "addressId",
"columnName": "addressId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "displayName",
"columnName": "displayName",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "signature",
"columnName": "signature",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "domainId",
"columnName": "domainId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "canSend",
"columnName": "canSend",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "canReceive",
"columnName": "canReceive",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "enabled",
"columnName": "enabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "order",
"columnName": "order",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"addressId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AddressEntity_addressId",
"unique": false,
"columnNames": [
"addressId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressEntity_addressId` ON `${TABLE_NAME}` (`addressId`)"
},
{
"name": "index_AddressEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "UserEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "AddressKeyEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`addressId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `flags` INTEGER NOT NULL, `token` TEXT, `signature` TEXT, `fingerprint` TEXT, `fingerprints` TEXT, `activation` TEXT, `active` INTEGER NOT NULL, PRIMARY KEY(`keyId`), FOREIGN KEY(`addressId`) REFERENCES `AddressEntity`(`addressId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "addressId",
"columnName": "addressId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyId",
"columnName": "keyId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "privateKey",
"columnName": "privateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isPrimary",
"columnName": "isPrimary",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "flags",
"columnName": "flags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "token",
"columnName": "token",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "signature",
"columnName": "signature",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "fingerprint",
"columnName": "fingerprint",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "fingerprints",
"columnName": "fingerprints",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "activation",
"columnName": "activation",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "active",
"columnName": "active",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"keyId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AddressKeyEntity_addressId",
"unique": false,
"columnNames": [
"addressId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_addressId` ON `${TABLE_NAME}` (`addressId`)"
},
{
"name": "index_AddressKeyEntity_keyId",
"unique": false,
"columnNames": [
"keyId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_keyId` ON `${TABLE_NAME}` (`keyId`)"
}
],
"foreignKeys": [
{
"table": "AddressEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"addressId"
],
"referencedColumns": [
"addressId"
]
}
]
},
{
"tableName": "KeySaltEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `keySalt` TEXT, PRIMARY KEY(`userId`, `keyId`))",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyId",
"columnName": "keyId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keySalt",
"columnName": "keySalt",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId",
"keyId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_KeySaltEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_KeySaltEntity_keyId",
"unique": false,
"columnNames": [
"keyId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_keyId` ON `${TABLE_NAME}` (`keyId`)"
}
],
"foreignKeys": []
},
{
"tableName": "PublicAddressEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `recipientType` INTEGER NOT NULL, `mimeType` TEXT, PRIMARY KEY(`email`))",
"fields": [
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "recipientType",
"columnName": "recipientType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "mimeType",
"columnName": "mimeType",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"email"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_PublicAddressEntity_email",
"unique": false,
"columnNames": [
"email"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_PublicAddressEntity_email` ON `${TABLE_NAME}` (`email`)"
}
],
"foreignKeys": []
},
{
"tableName": "PublicAddressKeyEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `flags` INTEGER NOT NULL, `publicKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, PRIMARY KEY(`email`, `publicKey`), FOREIGN KEY(`email`) REFERENCES `PublicAddressEntity`(`email`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "flags",
"columnName": "flags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "publicKey",
"columnName": "publicKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isPrimary",
"columnName": "isPrimary",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"email",
"publicKey"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_PublicAddressKeyEntity_email",
"unique": false,
"columnNames": [
"email"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_PublicAddressKeyEntity_email` ON `${TABLE_NAME}` (`email`)"
}
],
"foreignKeys": [
{
"table": "PublicAddressEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"email"
],
"referencedColumns": [
"email"
]
}
]
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f043b799940e4857395390ed2057c07c')"
]
}
}

View File

@ -0,0 +1,954 @@
{
"formatVersion": 1,
"database": {
"version": 5,
"identityHash": "85442139ccecab91d7b330ca02e9c55e",
"entities": [
{
"tableName": "AccountEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `username` TEXT NOT NULL, `email` TEXT, `state` TEXT NOT NULL, `sessionId` TEXT, `sessionState` TEXT, PRIMARY KEY(`userId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "username",
"columnName": "username",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "state",
"columnName": "state",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "sessionState",
"columnName": "sessionState",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_AccountEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "NO ACTION",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "AccountMetadataEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `product` TEXT NOT NULL, `primaryAtUtc` INTEGER NOT NULL, PRIMARY KEY(`userId`, `product`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "primaryAtUtc",
"columnName": "primaryAtUtc",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"userId",
"product"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AccountMetadataEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_AccountMetadataEntity_product",
"unique": false,
"columnNames": [
"product"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_product` ON `${TABLE_NAME}` (`product`)"
},
{
"name": "index_AccountMetadataEntity_primaryAtUtc",
"unique": false,
"columnNames": [
"primaryAtUtc"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AccountMetadataEntity_primaryAtUtc` ON `${TABLE_NAME}` (`primaryAtUtc`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "SessionEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `sessionId` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `refreshToken` TEXT NOT NULL, `scopes` TEXT NOT NULL, `product` TEXT NOT NULL, PRIMARY KEY(`sessionId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "accessToken",
"columnName": "accessToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "refreshToken",
"columnName": "refreshToken",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "scopes",
"columnName": "scopes",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "product",
"columnName": "product",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_SessionEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
},
{
"name": "index_SessionEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "SessionDetailsEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sessionId` TEXT NOT NULL, `initialEventId` TEXT NOT NULL, `requiredAccountType` TEXT NOT NULL, `secondFactorEnabled` INTEGER NOT NULL, `twoPassModeEnabled` INTEGER NOT NULL, `password` TEXT, PRIMARY KEY(`sessionId`), FOREIGN KEY(`sessionId`) REFERENCES `SessionEntity`(`sessionId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "sessionId",
"columnName": "sessionId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "initialEventId",
"columnName": "initialEventId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "requiredAccountType",
"columnName": "requiredAccountType",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "secondFactorEnabled",
"columnName": "secondFactorEnabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "twoPassModeEnabled",
"columnName": "twoPassModeEnabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "password",
"columnName": "password",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"sessionId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_SessionDetailsEntity_sessionId",
"unique": false,
"columnNames": [
"sessionId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_SessionDetailsEntity_sessionId` ON `${TABLE_NAME}` (`sessionId`)"
}
],
"foreignKeys": [
{
"table": "SessionEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"sessionId"
],
"referencedColumns": [
"sessionId"
]
}
]
},
{
"tableName": "UserEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `email` TEXT, `name` TEXT, `displayName` TEXT, `currency` TEXT NOT NULL, `credit` INTEGER NOT NULL, `usedSpace` INTEGER NOT NULL, `maxSpace` INTEGER NOT NULL, `maxUpload` INTEGER NOT NULL, `role` INTEGER, `private` INTEGER NOT NULL, `subscribed` INTEGER NOT NULL, `services` INTEGER NOT NULL, `delinquent` INTEGER, `passphrase` BLOB, PRIMARY KEY(`userId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "displayName",
"columnName": "displayName",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "currency",
"columnName": "currency",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "credit",
"columnName": "credit",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "usedSpace",
"columnName": "usedSpace",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "maxSpace",
"columnName": "maxSpace",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "maxUpload",
"columnName": "maxUpload",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "role",
"columnName": "role",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "private",
"columnName": "private",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "subscribed",
"columnName": "subscribed",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "services",
"columnName": "services",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "delinquent",
"columnName": "delinquent",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "passphrase",
"columnName": "passphrase",
"affinity": "BLOB",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_UserEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_UserEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "AccountEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "UserKeyEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `fingerprint` TEXT, `activation` TEXT, PRIMARY KEY(`keyId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyId",
"columnName": "keyId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "privateKey",
"columnName": "privateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isPrimary",
"columnName": "isPrimary",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "fingerprint",
"columnName": "fingerprint",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "activation",
"columnName": "activation",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"keyId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_UserKeyEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_UserKeyEntity_keyId",
"unique": false,
"columnNames": [
"keyId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_keyId` ON `${TABLE_NAME}` (`keyId`)"
}
],
"foreignKeys": [
{
"table": "UserEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "AddressEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `addressId` TEXT NOT NULL, `email` TEXT NOT NULL, `displayName` TEXT, `signature` TEXT, `domainId` TEXT, `canSend` INTEGER NOT NULL, `canReceive` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `type` INTEGER, `order` INTEGER NOT NULL, PRIMARY KEY(`addressId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "addressId",
"columnName": "addressId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "displayName",
"columnName": "displayName",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "signature",
"columnName": "signature",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "domainId",
"columnName": "domainId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "canSend",
"columnName": "canSend",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "canReceive",
"columnName": "canReceive",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "enabled",
"columnName": "enabled",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "order",
"columnName": "order",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"addressId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AddressEntity_addressId",
"unique": false,
"columnNames": [
"addressId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressEntity_addressId` ON `${TABLE_NAME}` (`addressId`)"
},
{
"name": "index_AddressEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressEntity_userId` ON `${TABLE_NAME}` (`userId`)"
}
],
"foreignKeys": [
{
"table": "UserEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"userId"
],
"referencedColumns": [
"userId"
]
}
]
},
{
"tableName": "AddressKeyEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`addressId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `flags` INTEGER NOT NULL, `token` TEXT, `signature` TEXT, `fingerprint` TEXT, `fingerprints` TEXT, `activation` TEXT, `active` INTEGER NOT NULL, PRIMARY KEY(`keyId`), FOREIGN KEY(`addressId`) REFERENCES `AddressEntity`(`addressId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "addressId",
"columnName": "addressId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyId",
"columnName": "keyId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "privateKey",
"columnName": "privateKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isPrimary",
"columnName": "isPrimary",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "flags",
"columnName": "flags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "token",
"columnName": "token",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "signature",
"columnName": "signature",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "fingerprint",
"columnName": "fingerprint",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "fingerprints",
"columnName": "fingerprints",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "activation",
"columnName": "activation",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "active",
"columnName": "active",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"keyId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_AddressKeyEntity_addressId",
"unique": false,
"columnNames": [
"addressId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_addressId` ON `${TABLE_NAME}` (`addressId`)"
},
{
"name": "index_AddressKeyEntity_keyId",
"unique": false,
"columnNames": [
"keyId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_keyId` ON `${TABLE_NAME}` (`keyId`)"
}
],
"foreignKeys": [
{
"table": "AddressEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"addressId"
],
"referencedColumns": [
"addressId"
]
}
]
},
{
"tableName": "KeySaltEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `keySalt` TEXT, PRIMARY KEY(`userId`, `keyId`))",
"fields": [
{
"fieldPath": "userId",
"columnName": "userId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keyId",
"columnName": "keyId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keySalt",
"columnName": "keySalt",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"userId",
"keyId"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_KeySaltEntity_userId",
"unique": false,
"columnNames": [
"userId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_userId` ON `${TABLE_NAME}` (`userId`)"
},
{
"name": "index_KeySaltEntity_keyId",
"unique": false,
"columnNames": [
"keyId"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_keyId` ON `${TABLE_NAME}` (`keyId`)"
}
],
"foreignKeys": []
},
{
"tableName": "PublicAddressEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `recipientType` INTEGER NOT NULL, `mimeType` TEXT, PRIMARY KEY(`email`))",
"fields": [
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "recipientType",
"columnName": "recipientType",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "mimeType",
"columnName": "mimeType",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"email"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_PublicAddressEntity_email",
"unique": false,
"columnNames": [
"email"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_PublicAddressEntity_email` ON `${TABLE_NAME}` (`email`)"
}
],
"foreignKeys": []
},
{
"tableName": "PublicAddressKeyEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`email` TEXT NOT NULL, `flags` INTEGER NOT NULL, `publicKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, PRIMARY KEY(`email`, `publicKey`), FOREIGN KEY(`email`) REFERENCES `PublicAddressEntity`(`email`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "email",
"columnName": "email",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "flags",
"columnName": "flags",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "publicKey",
"columnName": "publicKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isPrimary",
"columnName": "isPrimary",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"email",
"publicKey"
],
"autoGenerate": false
},
"indices": [
{
"name": "index_PublicAddressKeyEntity_email",
"unique": false,
"columnNames": [
"email"
],
"createSql": "CREATE INDEX IF NOT EXISTS `index_PublicAddressKeyEntity_email` ON `${TABLE_NAME}` (`email`)"
}
],
"foreignKeys": [
{
"table": "PublicAddressEntity",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"email"
],
"referencedColumns": [
"email"
]
}
]
},
{
"tableName": "HumanVerificationEntity",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`clientId` TEXT NOT NULL, `clientIdType` TEXT NOT NULL, `verificationMethods` TEXT NOT NULL, `captchaVerificationToken` TEXT, `state` TEXT NOT NULL, `humanHeaderTokenType` TEXT, `humanHeaderTokenCode` TEXT, PRIMARY KEY(`clientId`))",
"fields": [
{
"fieldPath": "clientId",
"columnName": "clientId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "clientIdType",
"columnName": "clientIdType",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "verificationMethods",
"columnName": "verificationMethods",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "captchaVerificationToken",
"columnName": "captchaVerificationToken",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "state",
"columnName": "state",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "humanHeaderTokenType",
"columnName": "humanHeaderTokenType",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "humanHeaderTokenCode",
"columnName": "humanHeaderTokenCode",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"clientId"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '85442139ccecab91d7b330ca02e9c55e')"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2021 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.android.core.coreexample.db
import android.content.Context
import androidx.room.Database
import androidx.room.TypeConverters
import me.proton.core.account.data.db.AccountConverters
import me.proton.core.account.data.db.AccountDatabase
import me.proton.core.account.data.entity.AccountEntity
import me.proton.core.account.data.entity.AccountMetadataEntity
import me.proton.core.account.data.entity.SessionDetailsEntity
import me.proton.core.account.data.entity.SessionEntity
import me.proton.core.crypto.android.keystore.CryptoConverters
import me.proton.core.data.db.BaseDatabase
import me.proton.core.data.db.CommonConverters
import me.proton.core.humanverification.data.db.HumanVerificationConverters
import me.proton.core.humanverification.data.db.HumanVerificationDatabase
import me.proton.core.humanverification.data.entity.HumanVerificationEntity
import me.proton.core.key.data.db.KeySaltDatabase
import me.proton.core.key.data.db.PublicAddressDatabase
import me.proton.core.key.data.entity.KeySaltEntity
import me.proton.core.key.data.entity.PublicAddressEntity
import me.proton.core.key.data.entity.PublicAddressKeyEntity
import me.proton.core.mailsettings.data.db.MailSettingsDatabase
import me.proton.core.mailsettings.data.entity.MailSettingsEntity
import me.proton.core.user.data.db.AddressDatabase
import me.proton.core.user.data.db.UserConverters
import me.proton.core.user.data.db.UserDatabase
import me.proton.core.user.data.entity.AddressEntity
import me.proton.core.user.data.entity.AddressKeyEntity
import me.proton.core.user.data.entity.UserEntity
import me.proton.core.user.data.entity.UserKeyEntity
@Database(
entities = [
// account-data
AccountEntity::class,
AccountMetadataEntity::class,
SessionEntity::class,
SessionDetailsEntity::class,
// user-data
UserEntity::class,
UserKeyEntity::class,
AddressEntity::class,
AddressKeyEntity::class,
// key-data
KeySaltEntity::class,
PublicAddressEntity::class,
PublicAddressKeyEntity::class,
// human-verification
HumanVerificationEntity::class,
// mail-settings
MailSettingsEntity::class
],
version = AppDatabase.version,
exportSchema = true
)
@TypeConverters(
CommonConverters::class,
AccountConverters::class,
UserConverters::class,
CryptoConverters::class,
HumanVerificationConverters::class
)
abstract class AppDatabase :
BaseDatabase(),
AccountDatabase,
UserDatabase,
AddressDatabase,
KeySaltDatabase,
HumanVerificationDatabase,
PublicAddressDatabase,
MailSettingsDatabase {
companion object {
const val name = "db-account-manager"
const val version = 6
val migrations = listOf(
AppDatabaseMigrations.MIGRATION_1_2,
AppDatabaseMigrations.MIGRATION_2_3,
AppDatabaseMigrations.MIGRATION_3_4,
AppDatabaseMigrations.MIGRATION_4_5,
AppDatabaseMigrations.MIGRATION_5_6,
)
fun buildDatabase(context: Context): AppDatabase =
databaseBuilder<AppDatabase>(context, name)
.apply { migrations.forEach { addMigrations(it) } }
.build()
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2021 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.android.core.coreexample.db
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.account.data.db.AccountDatabase
import me.proton.core.humanverification.data.db.HumanVerificationDatabase
import me.proton.core.key.data.db.KeySaltDatabase
import me.proton.core.key.data.db.PublicAddressDatabase
import me.proton.core.mailsettings.data.db.MailSettingsDatabase
import me.proton.core.user.data.db.AddressDatabase
import me.proton.core.user.data.db.UserDatabase
object AppDatabaseMigrations {
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
AccountDatabase.MIGRATION_0.migrate(database)
AccountDatabase.MIGRATION_1.migrate(database)
}
}
val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
AccountDatabase.MIGRATION_2.migrate(database)
UserDatabase.MIGRATION_0.migrate(database)
AddressDatabase.MIGRATION_0.migrate(database)
KeySaltDatabase.MIGRATION_0.migrate(database)
PublicAddressDatabase.MIGRATION_0.migrate(database)
}
}
val MIGRATION_3_4 = object : Migration(3, 4) {
override fun migrate(database: SupportSQLiteDatabase) {
AddressDatabase.MIGRATION_1.migrate(database)
}
}
val MIGRATION_4_5 = object : Migration(4, 5) {
override fun migrate(database: SupportSQLiteDatabase) {
AccountDatabase.MIGRATION_3.migrate(database)
HumanVerificationDatabase.MIGRATION_0.migrate(database)
}
}
val MIGRATION_5_6 = object : Migration(5, 6) {
override fun migrate(database: SupportSQLiteDatabase) {
MailSettingsDatabase.MIGRATION_0.migrate(database)
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2021 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.android.core.coreexample.di
import android.content.Context
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import me.proton.android.core.coreexample.db.AppDatabase
import me.proton.core.account.data.db.AccountDatabase
import me.proton.core.humanverification.data.db.HumanVerificationDatabase
import me.proton.core.key.data.db.KeySaltDatabase
import me.proton.core.key.data.db.PublicAddressDatabase
import me.proton.core.mailsettings.data.db.MailSettingsDatabase
import me.proton.core.user.data.db.AddressDatabase
import me.proton.core.user.data.db.UserDatabase
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object AppDatabaseModule {
@Provides
@Singleton
fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase =
AppDatabase.buildDatabase(context)
}
@Module
@InstallIn(SingletonComponent::class)
abstract class AppDatabaseBindsModule {
@Binds
abstract fun provideAccountDatabase(appDatabase: AppDatabase): AccountDatabase
@Binds
abstract fun provideUserDatabase(appDatabase: AppDatabase): UserDatabase
@Binds
abstract fun provideAddressDatabase(appDatabase: AppDatabase): AddressDatabase
@Binds
abstract fun provideKeySaltDatabase(appDatabase: AppDatabase): KeySaltDatabase
@Binds
abstract fun providePublicAddressDatabase(appDatabase: AppDatabase): PublicAddressDatabase
@Binds
abstract fun provideHumanVerificationDatabase(appDatabase: AppDatabase): HumanVerificationDatabase
@Binds
abstract fun provideMailSettingsDatabase(appDatabase: AppDatabase): MailSettingsDatabase
}

View File

@ -18,39 +18,16 @@
package me.proton.android.core.coreexample.di
import android.content.Context
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import me.proton.android.core.coreexample.Constants.BASE_URL
import me.proton.android.core.coreexample.CoreExampleLogger
import me.proton.android.core.coreexample.api.CoreExampleApiClient
import me.proton.android.core.coreexample.api.CoreExampleRepository
import me.proton.core.account.domain.entity.AccountType
import me.proton.core.auth.domain.ClientSecret
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.domain.entity.Product
import me.proton.core.network.data.ApiManagerFactory
import me.proton.core.network.data.ApiProvider
import me.proton.core.network.data.NetworkManager
import me.proton.core.network.data.NetworkPrefs
import me.proton.core.network.data.ProtonCookieStore
import me.proton.core.network.data.client.ClientIdProviderImpl
import me.proton.core.network.domain.ApiClient
import me.proton.core.network.domain.NetworkManager
import me.proton.core.network.domain.NetworkPrefs
import me.proton.core.network.domain.client.ClientIdProvider
import me.proton.core.network.domain.humanverification.HumanVerificationListener
import me.proton.core.network.domain.humanverification.HumanVerificationProvider
import me.proton.core.network.domain.server.ServerTimeListener
import me.proton.core.network.domain.session.SessionListener
import me.proton.core.network.domain.session.SessionProvider
import me.proton.core.util.kotlin.Logger
import javax.inject.Singleton
@ -77,79 +54,8 @@ object ApplicationModule {
fun provideLogger(): Logger =
CoreExampleLogger()
@Provides
@Singleton
fun provideNetworkManager(@ApplicationContext context: Context): NetworkManager =
NetworkManager(context)
@Provides
@Singleton
fun provideNetworkPrefs(@ApplicationContext context: Context) =
NetworkPrefs(context)
@Provides
@Singleton
fun provideProtonCookieStore(@ApplicationContext context: Context): ProtonCookieStore =
ProtonCookieStore(context)
@Provides
@Singleton
fun provideClientIdProvider(protonCookieStore: ProtonCookieStore): ClientIdProvider =
ClientIdProviderImpl(BASE_URL, protonCookieStore)
@Provides
@Singleton
fun provideServerTimeListener(context: CryptoContext) = object : ServerTimeListener {
override fun onServerTimeUpdated(epochSeconds: Long) {
context.pgpCrypto.updateTime(epochSeconds)
}
}
@Provides
@Singleton
fun provideApiFactory(
logger: Logger,
apiClient: ApiClient,
clientIdProvider: ClientIdProvider,
serverTimeListener: ServerTimeListener,
networkManager: NetworkManager,
networkPrefs: NetworkPrefs,
protonCookieStore: ProtonCookieStore,
sessionProvider: SessionProvider,
sessionListener: SessionListener,
humanVerificationProvider: HumanVerificationProvider,
humanVerificationListener: HumanVerificationListener
): ApiManagerFactory = ApiManagerFactory(
BASE_URL,
apiClient,
clientIdProvider,
serverTimeListener,
logger,
networkManager,
networkPrefs,
sessionProvider,
sessionListener,
humanVerificationProvider,
humanVerificationListener,
protonCookieStore,
CoroutineScope(Job() + Dispatchers.Default),
emptyArray(), emptyList()
)
@Provides
@Singleton
fun provideApiProvider(apiManagerFactory: ApiManagerFactory, sessionProvider: SessionProvider): ApiProvider =
ApiProvider(apiManagerFactory, sessionProvider)
@Provides
@Singleton
fun provideCoreExampleRepository(apiProvider: ApiProvider): CoreExampleRepository =
CoreExampleRepository(apiProvider)
}
@Module
@InstallIn(SingletonComponent::class)
abstract class ApplicationBindsModule {
@Binds
abstract fun provideApiClient(coreExampleApiClient: CoreExampleApiClient): ApiClient
}

View File

@ -24,11 +24,11 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import me.proton.android.core.coreexample.BuildConfig
import me.proton.core.accountmanager.data.db.AccountManagerDatabase
import me.proton.core.crypto.common.keystore.KeyStoreCrypto
import me.proton.core.humanverification.data.HumanVerificationListenerImpl
import me.proton.core.humanverification.data.HumanVerificationManagerImpl
import me.proton.core.humanverification.data.HumanVerificationProviderImpl
import me.proton.core.humanverification.data.db.HumanVerificationDatabase
import me.proton.core.humanverification.data.repository.HumanVerificationRepositoryImpl
import me.proton.core.humanverification.data.repository.UserVerificationRepositoryImpl
import me.proton.core.humanverification.domain.HumanVerificationManager
@ -72,7 +72,7 @@ object HumanVerificationModule {
@Provides
@Singleton
fun provideHumanVerificationRepository(
db: AccountManagerDatabase,
db: HumanVerificationDatabase,
keyStoreCrypto: KeyStoreCrypto
): HumanVerificationRepository =
HumanVerificationRepositoryImpl(db, keyStoreCrypto)

View File

@ -22,9 +22,9 @@ import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import me.proton.core.accountmanager.data.db.AccountManagerDatabase
import me.proton.core.mailmessage.data.repository.EmailMessageRepositoryImpl
import me.proton.core.mailmessage.domain.repository.EmailMessageRepository
import me.proton.core.mailsettings.data.db.MailSettingsDatabase
import me.proton.core.mailsettings.data.repository.MailSettingsRepositoryImpl
import me.proton.core.mailsettings.domain.repository.MailSettingsRepository
import me.proton.core.network.data.ApiProvider
@ -43,7 +43,7 @@ object MailModule {
@Provides
@Singleton
fun provideMailSettingsRepositoryImpl(
db: AccountManagerDatabase,
db: MailSettingsDatabase,
provider: ApiProvider
): MailSettingsRepository = MailSettingsRepositoryImpl(db, provider)
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2021 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.android.core.coreexample.di
import android.content.Context
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import me.proton.android.core.coreexample.Constants
import me.proton.android.core.coreexample.api.CoreExampleApiClient
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.network.data.ApiManagerFactory
import me.proton.core.network.data.ApiProvider
import me.proton.core.network.data.NetworkManager
import me.proton.core.network.data.NetworkPrefs
import me.proton.core.network.data.ProtonCookieStore
import me.proton.core.network.data.client.ClientIdProviderImpl
import me.proton.core.network.domain.ApiClient
import me.proton.core.network.domain.NetworkManager
import me.proton.core.network.domain.NetworkPrefs
import me.proton.core.network.domain.client.ClientIdProvider
import me.proton.core.network.domain.humanverification.HumanVerificationListener
import me.proton.core.network.domain.humanverification.HumanVerificationProvider
import me.proton.core.network.domain.server.ServerTimeListener
import me.proton.core.network.domain.session.SessionListener
import me.proton.core.network.domain.session.SessionProvider
import me.proton.core.util.kotlin.Logger
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class NetworkModule {
@Provides
@Singleton
fun provideNetworkManager(@ApplicationContext context: Context): NetworkManager =
NetworkManager(context)
@Provides
@Singleton
fun provideNetworkPrefs(@ApplicationContext context: Context) =
NetworkPrefs(context)
@Provides
@Singleton
fun provideProtonCookieStore(@ApplicationContext context: Context): ProtonCookieStore =
ProtonCookieStore(context)
@Provides
@Singleton
fun provideClientIdProvider(protonCookieStore: ProtonCookieStore): ClientIdProvider =
ClientIdProviderImpl(Constants.BASE_URL, protonCookieStore)
@Provides
@Singleton
fun provideServerTimeListener(context: CryptoContext) = object : ServerTimeListener {
override fun onServerTimeUpdated(epochSeconds: Long) {
context.pgpCrypto.updateTime(epochSeconds)
}
}
@Provides
@Singleton
fun provideApiFactory(
logger: Logger,
apiClient: ApiClient,
clientIdProvider: ClientIdProvider,
serverTimeListener: ServerTimeListener,
networkManager: NetworkManager,
networkPrefs: NetworkPrefs,
protonCookieStore: ProtonCookieStore,
sessionProvider: SessionProvider,
sessionListener: SessionListener,
humanVerificationProvider: HumanVerificationProvider,
humanVerificationListener: HumanVerificationListener
): ApiManagerFactory = ApiManagerFactory(
Constants.BASE_URL,
apiClient,
clientIdProvider,
serverTimeListener,
logger,
networkManager,
networkPrefs,
sessionProvider,
sessionListener,
humanVerificationProvider,
humanVerificationListener,
protonCookieStore,
CoroutineScope(Job() + Dispatchers.Default),
emptyArray(), emptyList()
)
@Provides
@Singleton
fun provideApiProvider(apiManagerFactory: ApiManagerFactory, sessionProvider: SessionProvider): ApiProvider =
ApiProvider(apiManagerFactory, sessionProvider)
}
@Module
@InstallIn(SingletonComponent::class)
abstract class NetworkBindsModule {
@Binds
abstract fun provideApiClient(coreExampleApiClient: CoreExampleApiClient): ApiClient
}

View File

@ -23,8 +23,9 @@ import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import me.proton.core.accountmanager.data.db.AccountManagerDatabase
import me.proton.core.crypto.common.context.CryptoContext
import me.proton.core.key.data.db.KeySaltDatabase
import me.proton.core.key.data.db.PublicAddressDatabase
import me.proton.core.key.data.repository.KeySaltRepositoryImpl
import me.proton.core.key.data.repository.PrivateKeyRepositoryImpl
import me.proton.core.key.data.repository.PublicAddressRepositoryImpl
@ -35,6 +36,8 @@ import me.proton.core.network.data.ApiProvider
import me.proton.core.user.data.UserAddressKeySecretProvider
import me.proton.core.user.data.UserAddressManagerImpl
import me.proton.core.user.data.UserManagerImpl
import me.proton.core.user.data.db.AddressDatabase
import me.proton.core.user.data.db.UserDatabase
import me.proton.core.user.data.repository.DomainRepositoryImpl
import me.proton.core.user.data.repository.UserAddressRepositoryImpl
import me.proton.core.user.data.repository.UserRepositoryImpl
@ -55,7 +58,7 @@ object UserManagerModule {
@Provides
@Singleton
fun provideUserRepositoryImpl(
db: AccountManagerDatabase,
db: UserDatabase,
provider: ApiProvider,
context: CryptoContext
): UserRepositoryImpl = UserRepositoryImpl(db, provider, context)
@ -63,7 +66,7 @@ object UserManagerModule {
@Provides
@Singleton
fun provideUserAddressRepository(
db: AccountManagerDatabase,
db: AddressDatabase,
provider: ApiProvider,
userRepository: UserRepository,
userAddressKeySecretProvider: UserAddressKeySecretProvider
@ -94,7 +97,7 @@ object UserManagerModule {
@Provides
@Singleton
fun provideKeySaltRepository(
db: AccountManagerDatabase,
db: KeySaltDatabase,
provider: ApiProvider
): KeySaltRepository = KeySaltRepositoryImpl(db, provider)
@ -107,7 +110,7 @@ object UserManagerModule {
@Provides
@Singleton
fun providePublicAddressKeyRepository(
db: AccountManagerDatabase,
db: PublicAddressDatabase,
provider: ApiProvider
): PublicAddressRepository = PublicAddressRepositoryImpl(db, provider)

View File

@ -23,7 +23,7 @@ plugins {
kotlin("android")
}
libVersion = Version(1, 0, 3)
libVersion = Version(1, 3, 1)
android()

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2021 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.data.db
import android.content.Context
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.withTransaction
abstract class BaseDatabase : RoomDatabase(), Database {
override suspend fun <R> inTransaction(block: suspend () -> R): R = withTransaction(block)
companion object {
inline fun <reified DB : RoomDatabase> databaseBuilder(
context: Context,
dbName: String
): Builder<DB> = Room.databaseBuilder(context, DB::class.java, dbName)
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2021 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.data.room.db.extension
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
/**
* Create and/or open a database that will be used for reading and writing.
*
* Any needed/defined migrations will be applied.
*
* Note: Make sure to call close when you no longer need the database
*/
fun RoomDatabase.open(): SupportSQLiteDatabase = openHelper.writableDatabase
/**
* Create and/or open a database and directly close it after creation/upgrade/migration.
*
* Any needed/defined migrations will be applied.
*/
fun RoomDatabase.openAndClose(): Unit = openHelper.writableDatabase.close()

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2021 Proton Technologies AG
* This file is part of Proton Technologies AG and ProtonCore.
*
* ProtonCore is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonCore is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.data.db.extension
import androidx.sqlite.db.SupportSQLiteDatabase
/**
* Get [table] columns name.
*/
fun SupportSQLiteDatabase.getTableColumns(table: String): List<String> {
return query("SELECT * FROM $table LIMIT 0").use { it.columnNames.toList() }
}
/**
* Recreate [table] with [columns] using [createTable] and [createIndices], and then copy the old table data to it.
*/
fun SupportSQLiteDatabase.recreateTable(
table: String,
createTable: SupportSQLiteDatabase.() -> Unit,
createIndices: SupportSQLiteDatabase.() -> Unit,
columns: List<String>
) {
val columnsSeparated = columns.joinToString(",")
execSQL("ALTER TABLE $table RENAME TO ${table}_old")
createTable.invoke(this)
execSQL("INSERT INTO $table($columnsSeparated) SELECT $columnsSeparated FROM ${table}_old")
execSQL("DROP TABLE ${table}_old")
createIndices.invoke(this)
}
/**
* Recreate [table] using [createTable] and [createIndices], and then copy the old table data to it.
*/
fun SupportSQLiteDatabase.recreateTable(
table: String,
createTable: SupportSQLiteDatabase.() -> Unit,
createIndices: SupportSQLiteDatabase.() -> Unit
) = recreateTable(table, createTable, createIndices, getTableColumns(table))
/**
* Add [column] to [table] with [type] and [defaultValue].
*/
fun SupportSQLiteDatabase.addTableColumn(
table: String,
column: String,
type: String,
defaultValue: String? = null
) {
val defaultValueSuffix = defaultValue?.let { "DEFAULT '$defaultValue'" } ?: ""
val sqlStatement = "ALTER TABLE $table ADD COLUMN $column $type $defaultValueSuffix"
execSQL(sqlStatement)
}
/**
* Drop [columns] from [table].
*
* Create a new table without the [columns], and then copy the old table data to it.
*
* Note: [createTable] and [createIndices] must be provided.
*/
fun SupportSQLiteDatabase.dropTableColumn(
table: String,
createTable: SupportSQLiteDatabase.() -> Unit,
createIndices: SupportSQLiteDatabase.() -> Unit,
columns: List<String>
) = recreateTable(table, createTable, createIndices, getTableColumns(table) - columns)
/**
* Drop [column] from [table].
*
* Create a new table without the [column], and then copy the old table data to it.
*
* Note: [createTable] and [createIndices] must be provided.
*/
fun SupportSQLiteDatabase.dropTableColumn(
table: String,
createTable: SupportSQLiteDatabase.() -> Unit,
createIndices: SupportSQLiteDatabase.() -> Unit,
column: String
) = dropTableColumn(table, createTable, createIndices, listOf(column))
/**
* Drop content from [table].
*/
fun SupportSQLiteDatabase.dropTableContent(table: String) {
execSQL("DELETE FROM $table")
}
/**
* Drop [table], if exist.
*/
fun SupportSQLiteDatabase.dropTable(table: String) {
execSQL("DROP TABLE IF EXISTS $table")
}

View File

@ -16,17 +16,10 @@
* along with ProtonCore. If not, see <https://www.gnu.org/licenses/>.
*/
package me.proton.core.accountmanager.data.db.migration
package me.proton.core.data.db.migration
import androidx.sqlite.db.SupportSQLiteDatabase
fun SupportSQLiteDatabase.addTableColumn(
table: String,
column: String,
type: String,
defaultValue: String? = null
) {
val defaultValueSuffix = defaultValue?.let { "DEFAULT '$defaultValue'" } ?: ""
val sqlStatement = "ALTER TABLE $table ADD COLUMN $column $type $defaultValueSuffix"
this.execSQL(sqlStatement)
interface DatabaseMigration {
fun migrate(database: SupportSQLiteDatabase)
}

View File

@ -40,7 +40,7 @@ internal fun initVersions() {
`material version` = "1.3.0" // Released: Feb 05, 2021
`android-paging version` = "2.1.2" // Released: Mar 18, 2020
`android-work version` = "2.2.0" // Released: Aug 16, 2019
`android-room version` = "2.4.0-alpha01" // Released: Apr 21, 2021
`android-room version` = "2.3.0" // Released: Apr 21, 2021
`android-test version` = "1.3.0" // Released: Aug 25, 2020
`robolectric version` = "4.4" // Released: Aug 24, 2020

View File

@ -23,7 +23,7 @@ plugins {
kotlin("android")
}
libVersion = Version(1, 2, 8)
libVersion = Version(1, 3, 1)
android()

View File

@ -26,7 +26,7 @@ plugins {
kotlin("kapt")
}
libVersion = Version(1, 2, 8)
libVersion = Version(1, 3, 1)
android(minSdk = 23)

View File

@ -18,8 +18,22 @@
package me.proton.core.humanverification.data.db
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.data.db.Database
import me.proton.core.data.db.migration.DatabaseMigration
interface HumanVerificationDatabase : Database {
fun humanVerificationDetailsDao(): HumanVerificationDetailsDao
companion object {
/**
* - Added Table HumanVerificationEntity.
*/
val MIGRATION_0 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Added Table HumanVerificationEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `HumanVerificationEntity` (`clientId` TEXT NOT NULL, `clientIdType` TEXT NOT NULL, `verificationMethods` TEXT NOT NULL, `captchaVerificationToken` TEXT, `state` TEXT NOT NULL, `humanHeaderTokenType` TEXT, `humanHeaderTokenCode` TEXT, PRIMARY KEY(`clientId`))")
}
}
}
}

View File

@ -23,7 +23,7 @@ plugins {
kotlin("jvm")
}
libVersion = Version(1, 2, 8)
libVersion = Version(1, 3, 1)
dependencies {

View File

@ -27,7 +27,7 @@ plugins {
id("dagger.hilt.android.plugin")
}
libVersion = Version(1, 2, 8)
libVersion = Version(1, 3, 1)
android(useDataBinding = true)

View File

@ -23,7 +23,7 @@ plugins {
kotlin("android")
}
libVersion = Version(1, 1, 5)
libVersion = Version(1, 3, 1)
android()

View File

@ -25,7 +25,7 @@ plugins {
kotlin("plugin.serialization")
}
libVersion = Version(1, 1, 5)
libVersion = Version(1, 3, 1)
android()

View File

@ -18,8 +18,24 @@
package me.proton.core.key.data.db
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.data.db.Database
import me.proton.core.data.db.migration.DatabaseMigration
interface KeySaltDatabase : Database {
fun keySaltDao(): KeySaltDao
companion object {
/**
* - Create Table KeySaltEntity.
*/
val MIGRATION_0 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Create Table KeySaltEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `KeySaltEntity` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `keySalt` TEXT, PRIMARY KEY(`userId`, `keyId`))")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_userId` ON `KeySaltEntity` (`userId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_KeySaltEntity_keyId` ON `KeySaltEntity` (`keyId`)")
}
}
}
}

View File

@ -18,10 +18,29 @@
package me.proton.core.key.data.db
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.data.db.Database
import me.proton.core.data.db.migration.DatabaseMigration
interface PublicAddressDatabase : Database {
fun publicAddressDao(): PublicAddressDao
fun publicAddressKeyDao(): PublicAddressKeyDao
fun publicAddressWithKeysDao(): PublicAddressWithKeysDao
companion object {
/**
* - Create Table PublicAddressEntity.
* - Create Table PublicAddressKeyEntity.
*/
val MIGRATION_0 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Create Table PublicAddressEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `PublicAddressEntity` (`email` TEXT NOT NULL, `recipientType` INTEGER NOT NULL, `mimeType` TEXT, PRIMARY KEY(`email`))")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_PublicAddressEntity_email` ON `PublicAddressEntity` (`email`)")
// Create Table PublicAddressKeyEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `PublicAddressKeyEntity` (`email` TEXT NOT NULL, `flags` INTEGER NOT NULL, `publicKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, PRIMARY KEY(`email`, `publicKey`), FOREIGN KEY(`email`) REFERENCES `PublicAddressEntity`(`email`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_PublicAddressKeyEntity_email` ON `PublicAddressKeyEntity` (`email`)")
}
}
}
}

View File

@ -23,7 +23,7 @@ plugins {
kotlin("jvm")
}
libVersion = Version(1, 1, 5)
libVersion = Version(1, 3, 1)
dependencies {
implementation(

View File

@ -23,7 +23,7 @@ plugins {
kotlin("android")
}
libVersion = Version(0, 2, 1)
libVersion = Version(1, 3, 1)
android()

View File

@ -24,7 +24,7 @@ plugins {
kotlin("plugin.serialization")
}
libVersion = Version(0, 2, 1)
libVersion = Version(1, 3, 1)
android()

View File

@ -18,9 +18,23 @@
package me.proton.core.mailsettings.data.db
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.data.db.Database
import me.proton.core.data.db.migration.DatabaseMigration
import me.proton.core.mailsettings.data.db.dao.MailSettingsDao
interface MailSettingsDatabase : Database {
fun mailSettingsDao(): MailSettingsDao
companion object {
/**
* - Added Table MailSettingsEntity.
*/
val MIGRATION_0 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Added Table MailSettingsEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `MailSettingsEntity` (`userId` TEXT NOT NULL, `displayName` TEXT, `signature` TEXT, `autoSaveContacts` INTEGER, `composerMode` INTEGER, `messageButtons` INTEGER, `showImages` INTEGER, `showMoved` INTEGER, `viewMode` INTEGER, `viewLayout` INTEGER, `swipeLeft` INTEGER, `swipeRight` INTEGER, `shortcuts` INTEGER, `pmSignature` INTEGER, `numMessagePerPage` INTEGER, `draftMimeType` TEXT, `receiveMimeType` TEXT, `showMimeType` TEXT, `enableFolderColor` INTEGER, `inheritParentFolderColor` INTEGER, `rightToLeft` INTEGER, `attachPublicKey` INTEGER, `sign` INTEGER, `pgpScheme` INTEGER, `promptPin` INTEGER, `stickyLabels` INTEGER, `confirmLink` INTEGER, PRIMARY KEY(`userId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
}
}
}
}

View File

@ -23,7 +23,7 @@ plugins {
kotlin("jvm")
}
libVersion = Version(0, 2, 1)
libVersion = Version(1, 3, 1)
dependencies {

View File

@ -23,7 +23,7 @@ plugins {
kotlin("android")
}
libVersion = Version(1, 1, 5)
libVersion = Version(1, 3, 1)
android()

View File

@ -25,7 +25,7 @@ plugins {
kotlin("plugin.serialization")
}
libVersion = Version(1, 1, 5)
libVersion = Version(1, 3, 1)
android()

View File

@ -18,11 +18,43 @@
package me.proton.core.user.data.db
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.data.db.Database
import me.proton.core.data.db.extension.addTableColumn
import me.proton.core.data.db.migration.DatabaseMigration
import me.proton.core.user.data.db.dao.AddressDao
import me.proton.core.user.data.db.dao.AddressWithKeysDao
interface AddressDatabase : Database, AddressKeyDatabase {
fun addressDao(): AddressDao
fun addressWithKeysDao(): AddressWithKeysDao
companion object {
/**
* - Create Table AddressEntity.
* - Create Table AddressKeyEntity.
*/
val MIGRATION_0 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Create Table AddressEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `AddressEntity` (`userId` TEXT NOT NULL, `addressId` TEXT NOT NULL, `email` TEXT NOT NULL, `displayName` TEXT, `domainId` TEXT, `canSend` INTEGER NOT NULL, `canReceive` INTEGER NOT NULL, `enabled` INTEGER NOT NULL, `type` INTEGER, `order` INTEGER NOT NULL, PRIMARY KEY(`addressId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AddressEntity_addressId` ON `AddressEntity` (`addressId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AddressEntity_userId` ON `AddressEntity` (`userId`)")
// Create Table AddressKeyEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `AddressKeyEntity` (`addressId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `flags` INTEGER NOT NULL, `token` TEXT, `signature` TEXT, `fingerprint` TEXT, `fingerprints` TEXT, `activation` TEXT, `active` INTEGER NOT NULL, PRIMARY KEY(`keyId`), FOREIGN KEY(`addressId`) REFERENCES `AddressEntity`(`addressId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_addressId` ON `AddressKeyEntity` (`addressId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_AddressKeyEntity_keyId` ON `AddressKeyEntity` (`keyId`)")
}
}
/**
* - Added AddressEntity.signature.
*/
val MIGRATION_1 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
database.addTableColumn(table = "AddressEntity", column = "signature", type = "TEXT")
}
}
}
}

View File

@ -18,11 +18,31 @@
package me.proton.core.user.data.db
import androidx.sqlite.db.SupportSQLiteDatabase
import me.proton.core.data.db.Database
import me.proton.core.data.db.migration.DatabaseMigration
import me.proton.core.user.data.db.dao.UserDao
import me.proton.core.user.data.db.dao.UserWithKeysDao
interface UserDatabase : Database, UserKeyDatabase {
fun userDao(): UserDao
fun userWithKeysDao(): UserWithKeysDao
companion object {
/**
* - Create Table UserEntity.
* - Create Table UserKeyEntity.
*/
val MIGRATION_0 = object : DatabaseMigration {
override fun migrate(database: SupportSQLiteDatabase) {
// Create Table UserEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `UserEntity` (`userId` TEXT NOT NULL, `email` TEXT, `name` TEXT, `displayName` TEXT, `currency` TEXT NOT NULL, `credit` INTEGER NOT NULL, `usedSpace` INTEGER NOT NULL, `maxSpace` INTEGER NOT NULL, `maxUpload` INTEGER NOT NULL, `role` INTEGER, `private` INTEGER NOT NULL, `subscribed` INTEGER NOT NULL, `services` INTEGER NOT NULL, `delinquent` INTEGER, `passphrase` BLOB, PRIMARY KEY(`userId`), FOREIGN KEY(`userId`) REFERENCES `AccountEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_UserEntity_userId` ON `UserEntity` (`userId`)")
// Create Table UserKeyEntity.
database.execSQL("CREATE TABLE IF NOT EXISTS `UserKeyEntity` (`userId` TEXT NOT NULL, `keyId` TEXT NOT NULL, `version` INTEGER NOT NULL, `privateKey` TEXT NOT NULL, `isPrimary` INTEGER NOT NULL, `fingerprint` TEXT, `activation` TEXT, PRIMARY KEY(`keyId`), FOREIGN KEY(`userId`) REFERENCES `UserEntity`(`userId`) ON UPDATE NO ACTION ON DELETE CASCADE )")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_userId` ON `UserKeyEntity` (`userId`)")
database.execSQL("CREATE INDEX IF NOT EXISTS `index_UserKeyEntity_keyId` ON `UserKeyEntity` (`keyId`)")
}
}
}
}

View File

@ -23,7 +23,7 @@ plugins {
kotlin("jvm")
}
libVersion = Version(1, 1, 5)
libVersion = Version(1, 3, 1)
dependencies {
implementation(