Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ class RecipientRepository @Inject constructor(

// Safety: Let's filter again for the flow logic to be 100% sure we are only setting timers for valid proofs
val validProDataList = proDataContext?.proDataList?.filter {
!it.isExpired(now) && !proDatabase.isRevoked(it.genIndexHash)
!it.isExpired(now) && !proDatabase.isRevoked(it.genIndexHash, snodeClock.get().currentTime())
}

if (changeSources != null) {
Expand Down Expand Up @@ -485,7 +485,7 @@ class RecipientRepository @Inject constructor(

// 1. Filter invalid proofs
proDataList?.removeAll {
it.isExpired(now) || proDatabase.isRevoked(it.genIndexHash)
it.isExpired(now) || proDatabase.isRevoked(it.genIndexHash, snodeClock.get().currentTime())
}

// 2. Determine base Pro Data from valid proofs or ProStatusManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int lokiV56 = 77;
private static final int lokiV57 = 78;
private static final int lokiV58 = 79;
private static final int lokiV59 = 80;

// Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
private static final int DATABASE_VERSION = lokiV58;
private static final int DATABASE_VERSION = lokiV59;
private static final int MIN_DATABASE_VERSION = lokiV7;
public static final String DATABASE_NAME = "session.db";

Expand Down Expand Up @@ -279,6 +280,8 @@ public void onCreate(SQLiteDatabase db) {
RecipientSettingsDatabase.Companion.migrateProStatusToProData(db);

SnodeDatabase.Companion.createTableAndMigrateData(db, true);

ProDatabase.Companion.addEffectiveFromColumn(db);
}

@Override
Expand Down Expand Up @@ -633,6 +636,10 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
SnodeDatabase.Companion.createTableAndMigrateData(db, true);
}

if (oldVersion < lokiV59) {
ProDatabase.Companion.addEffectiveFromColumn(db);
}

db.setTransactionSuccessful();
} finally {
db.endTransaction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ class ProStatusManager @Inject constructor(
.asSequence()
.filterIsInstance<Conversation.WithProProofInfo>()
.filter { convo ->
convo.proProofInfo?.genIndexHash?.let { proDatabase.isRevoked(it.data.toHexString()) } == true
convo.proProofInfo?.genIndexHash?.let { proDatabase.isRevoked(it.data.toHexString(), snodeClock.currentTime()) } == true
}
.onEach { convo ->
convo.proProofInfo = null
Expand Down Expand Up @@ -379,7 +379,7 @@ class ProStatusManager @Inject constructor(
.onStart { emit(Unit) },

{ proofGenIndexHash, _ ->
proofGenIndexHash.takeIf { proDatabase.isRevoked(it) }
proofGenIndexHash.takeIf { proDatabase.isRevoked(it, snodeClock.currentTime()) }
}
)
.filterNotNull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import androidx.work.BackoffPolicy
import androidx.work.Constraints
import androidx.work.CoroutineWorker
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.ExistingWorkPolicy
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.WorkerParameters
Expand All @@ -32,7 +34,7 @@ import kotlin.coroutines.cancellation.CancellationException
*/
@HiltWorker
class RevocationListPollingWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted private val context: Context,
@Assisted params: WorkerParameters,
private val proDatabase: ProDatabase,
private val getProRevocationApiFactory: GetProRevocationApi.Factory,
Expand All @@ -56,6 +58,19 @@ class RevocationListPollingWorker @AssistedInject constructor(

proDatabase.pruneRevocations(snodeClock.currentTime())

// Arrange next polling
WorkManager.getInstance(context)
.beginUniqueWork(WORK_NAME, ExistingWorkPolicy.APPEND,
OneTimeWorkRequestBuilder<RevocationListPollingWorker>()
.setInitialDelay(response.retryInSeconds, TimeUnit.SECONDS)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, Duration.ofSeconds(10))
.setConstraints(Constraints(requiredNetworkType = NetworkType.CONNECTED))
.build()
)
.enqueue()

Log.d(TAG, "Arranged next polling in ${response.retryInSeconds} seconds")

return Result.success()
} catch (e: Exception) {
if (e is CancellationException) {
Expand All @@ -78,14 +93,16 @@ class RevocationListPollingWorker @AssistedInject constructor(

suspend fun schedule(context: Context) {
WorkManager.getInstance(context)
.enqueueUniquePeriodicWork(WORK_NAME, ExistingPeriodicWorkPolicy.KEEP,
PeriodicWorkRequestBuilder<RevocationListPollingWorker>(Duration.ofMinutes(15))
.setInitialDelay(0L, TimeUnit.MILLISECONDS)
.beginUniqueWork(WORK_NAME, ExistingWorkPolicy.KEEP,
OneTimeWorkRequestBuilder<RevocationListPollingWorker>()
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, Duration.ofSeconds(10))
.setConstraints(Constraints(requiredNetworkType = NetworkType.CONNECTED))
.build()
)
.enqueue()
.await()

WorkManager.getInstance(context)
}

suspend fun cancel(context: Context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import org.session.libsession.utilities.serializable.InstantAsMillisSerializer
import java.time.Instant
import kotlin.time.Duration

class GetProRevocationApi @AssistedInject constructor(
@Assisted private val ticket: Long?,
Expand Down Expand Up @@ -41,14 +42,20 @@ class GetProRevocationApi @AssistedInject constructor(
@Serializable
class ProRevocations(
val ticket: Long,
val items: List<Item>
val items: List<Item>,
@SerialName("retry_in_s")
val retryInSeconds: Long,
) {
@Serializable
class Item(
@Serializable(with = InstantAsMillisSerializer::class)
@SerialName("expiry_unix_ts_ms")
val expiry: Instant,

@Serializable(with = InstantAsMillisSerializer::class)
@SerialName("effective_unix_ts_ms")
val effectiveFrom: Instant,

@SerialName("gen_index_hash")
val genIndexHash: String,
)
Expand Down
28 changes: 20 additions & 8 deletions app/src/main/java/org/thoughtcrime/securesms/pro/db/ProDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,16 @@ class ProDatabase @Inject constructor(
//language=roomsql
compileStatement(
"""
INSERT INTO pro_revocations (gen_index_hash, expiry_ms)
VALUES (?, ?)
ON CONFLICT DO UPDATE SET expiry_ms=excluded.expiry_ms WHERE expiry_ms != excluded.expiry_ms
INSERT INTO pro_revocations (gen_index_hash, expiry_ms, effective_from_ms)
VALUES (?, ?, ?)
ON CONFLICT DO UPDATE SET expiry_ms=excluded.expiry_ms, effective_from_ms=excluded.effective_from_ms
WHERE expiry_ms != excluded.expiry_ms OR effective_from_ms != excluded.effective_from_ms
"""
).use { stmt ->
for (item in data) {
stmt.bindString(1, item.genIndexHash)
stmt.bindLong(2, item.expiry.toEpochMilli())
stmt.bindLong(3, item.effectiveFrom.toEpochMilli())
changes += stmt.executeUpdateDelete()
stmt.clearBindings()
}
Expand Down Expand Up @@ -109,17 +111,17 @@ class ProDatabase @Inject constructor(
Log.d(TAG, "Pruned ${pruned.size} expired pro revocations")
}

fun isRevoked(genIndexHash: String): Boolean {
fun isRevoked(genIndexHash: String, now: Instant): Boolean {
if (cache[genIndexHash] != null) {
return true
}

//language=roomsql
readableDatabase.query("""
SELECT 1 FROM pro_revocations
WHERE gen_index_hash = ?
WHERE gen_index_hash = ?1 AND ?2 >= effective_from_ms AND ?2 < expiry_ms
LIMIT 1
""", arrayOf(genIndexHash)).use { cursor ->
""", arrayOf<Any>(genIndexHash, now.toEpochMilli())).use { cursor ->
if (cursor.moveToFirst()) {
cache.put(genIndexHash, Unit)
return true
Expand All @@ -136,10 +138,10 @@ class ProDatabase @Inject constructor(
val proDetailsChangeNotification: SharedFlow<Unit> get() = mutableProDetailsChangeNotification

fun getProDetailsAndLastUpdated(): Pair<ProDetails, Instant>? {
return readableDatabase.rawQuery("""
return readableDatabase.query("""
SELECT name, value FROM pro_state
WHERE name IN (?, ?)
""", STATE_PRO_DETAILS, STATE_PRO_DETAILS_UPDATED_AT).use { cursor ->
""", arrayOf(STATE_PRO_DETAILS, STATE_PRO_DETAILS_UPDATED_AT)).use { cursor ->
var details: ProDetails? = null
var updatedAt: Instant? = null

Expand Down Expand Up @@ -192,6 +194,7 @@ class ProDatabase @Inject constructor(

fun createTable(db: SupportSQLiteDatabase) {
// A table to hold the list of pro revocations
//language=roomsql
db.execSQL("""
CREATE TABLE pro_revocations(
gen_index_hash TEXT NOT NULL PRIMARY KEY,
Expand All @@ -200,12 +203,21 @@ class ProDatabase @Inject constructor(
""")

// A table to hold state related to pro
//language=roomsql
db.execSQL("""
CREATE TABLE pro_state(
name TEXT NOT NULL PRIMARY KEY,
value TEXT
) WITHOUT ROWID"""
)
}

fun addEffectiveFromColumn(db: SupportSQLiteDatabase) {
//language=roomsql
db.execSQL("""
ALTER TABLE pro_revocations
ADD COLUMN effective_from_ms INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP
""")
}
}
}
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ kotlinxImmutableVersion = "0.4.0"
kryoVersion = "5.6.2"
kspVersion = "2.3.6"
legacySupportV13Version = "1.0.0"
libsessionUtilAndroidVersion = "1.1.0-7-g9dd1c98"
libsessionUtilAndroidVersion = "1.1.0-8-g02c4cde"
media3ExoplayerVersion = "1.9.2"
mockitoCoreVersion = "5.22.0"
navVersion = "2.9.7"
Expand Down