Never allow My Story to be deleted
This commit is contained in:
parent
185035784c
commit
f64e718ba2
@ -14,13 +14,20 @@ public class StoryManager {
|
||||
cacheAreViewReceiptsEnabled()
|
||||
|
||||
appReadiness.runNowOrWhenAppDidBecomeReadyAsync {
|
||||
SSKEnvironment.shared.databaseStorageRef.asyncWrite { transaction in
|
||||
// Create My Story thread if necessary
|
||||
TSPrivateStoryThread.getOrCreateMyStory(transaction: transaction)
|
||||
let db = DependenciesBridge.shared.db
|
||||
let storageServiceManager = SSKEnvironment.shared.storageServiceManagerRef
|
||||
let privateStoryThreadDeletionManager = DependenciesBridge.shared.privateStoryThreadDeletionManager
|
||||
|
||||
db.asyncWrite { tx in
|
||||
if TSPrivateStoryThread.getMyStory(transaction: tx) == nil {
|
||||
let myStory = TSPrivateStoryThread.getOrCreateMyStory(transaction: tx)
|
||||
storageServiceManager.recordPendingUpdates(
|
||||
updatedStoryDistributionListIds: [myStory.distributionListIdentifier!],
|
||||
)
|
||||
}
|
||||
|
||||
if CurrentAppContext().isMainApp {
|
||||
DependenciesBridge.shared.privateStoryThreadDeletionManager
|
||||
.cleanUpDeletedTimestamps(tx: transaction)
|
||||
privateStoryThreadDeletionManager.cleanUpDeletedTimestamps(tx: tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,6 +331,7 @@ public class GRDBSchemaMigrator {
|
||||
case migrateSecureValueRecovery
|
||||
case wipeCachedSVRBAuthCredentials
|
||||
case addMimeTypeToMessageAttachmentReference
|
||||
case purgeMyStoryDeletedAtTimestamp
|
||||
|
||||
// NOTE: Every time we add a migration id, consider
|
||||
// incrementing grdbSchemaVersionLatest.
|
||||
@ -454,7 +455,7 @@ public class GRDBSchemaMigrator {
|
||||
}
|
||||
|
||||
public static let grdbSchemaVersionDefault: UInt = 0
|
||||
public static let grdbSchemaVersionLatest: UInt = 143
|
||||
public static let grdbSchemaVersionLatest: UInt = 144
|
||||
|
||||
private class DatabaseMigratorWrapper {
|
||||
// Run with immediate (or disabled) foreign key checks so that pre-existing
|
||||
@ -5184,6 +5185,24 @@ public class GRDBSchemaMigrator {
|
||||
return .success(())
|
||||
}
|
||||
|
||||
migrator.registerMigration(.purgeMyStoryDeletedAtTimestamp) { tx in
|
||||
// "My Story" should never be deleted, but we've seen reports where
|
||||
// it has been marked as such. Remove it from the deleted-story
|
||||
// store if necessary; we (at the time of writing) create the My Story
|
||||
// thread on app launch and have guards against deleting it again in
|
||||
// the future.
|
||||
try tx.database.execute(
|
||||
sql: """
|
||||
DELETE FROM keyvalue WHERE collection = ? AND key = ?
|
||||
""",
|
||||
arguments: [
|
||||
"TSPrivateStoryThread+DeletedAtTimestamp",
|
||||
"00000000-0000-0000-0000-000000000000",
|
||||
],
|
||||
)
|
||||
return .success(())
|
||||
}
|
||||
|
||||
// MARK: - Schema Migration Insertion Point
|
||||
}
|
||||
|
||||
|
||||
@ -2077,6 +2077,12 @@ class StorageServiceStoryDistributionListRecordUpdater: StorageServiceRecordUpda
|
||||
// The story has been deleted on another device, record that
|
||||
// and ensure we don't try and put it back.
|
||||
guard record.deletedAtTimestamp == 0 else {
|
||||
if uniqueId.uuidString == TSPrivateStoryThread.myStoryUniqueId {
|
||||
// My Story should never be deleted. If someone put such in
|
||||
// Storage Service, ignore and overwrite it.
|
||||
return .merged(needsUpdate: true, identifier)
|
||||
}
|
||||
|
||||
if let existingStory {
|
||||
threadRemover.remove(existingStory, tx: transaction)
|
||||
}
|
||||
|
||||
@ -84,7 +84,15 @@ final class PrivateStoryThreadDeletionManagerImpl: PrivateStoryThreadDeletionMan
|
||||
return
|
||||
}
|
||||
|
||||
guard let uniqueId = identifier.uuidString else { return }
|
||||
guard let uniqueId = identifier.uuidString else {
|
||||
return
|
||||
}
|
||||
|
||||
if uniqueId == TSPrivateStoryThread.myStoryUniqueId {
|
||||
owsFailDebug("Refusing to record My Story as deleted.", logger: logger)
|
||||
return
|
||||
}
|
||||
|
||||
deletedAtTimestampStore.setUInt64(timestamp, key: uniqueId, transaction: tx)
|
||||
}
|
||||
|
||||
|
||||
@ -145,7 +145,7 @@ public final class TSPrivateStoryThread: TSThread {
|
||||
"00000000-0000-0000-0000-000000000000"
|
||||
}
|
||||
|
||||
public class func getMyStory(transaction: DBReadTransaction) -> TSPrivateStoryThread! {
|
||||
public class func getMyStory(transaction: DBReadTransaction) -> TSPrivateStoryThread? {
|
||||
fetchPrivateStoryThreadViaCache(uniqueId: myStoryUniqueId, transaction: transaction)
|
||||
}
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ private class MyStorySettingsDataSource: NSObject {
|
||||
myStoryThread,
|
||||
myStoryThreadRecipientIds,
|
||||
) = databaseStorage.read { transaction -> (Bool, TSPrivateStoryThread, [SignalRecipient.RowId]) in
|
||||
let myStoryThread: TSPrivateStoryThread = TSPrivateStoryThread.getMyStory(transaction: transaction)
|
||||
let myStoryThread: TSPrivateStoryThread = TSPrivateStoryThread.getMyStory(transaction: transaction)!
|
||||
return (
|
||||
StoryManager.hasSetMyStoriesPrivacy(transaction: transaction),
|
||||
myStoryThread,
|
||||
@ -249,7 +249,7 @@ private class MyStorySettingsDataSource: NSObject {
|
||||
|
||||
@objc
|
||||
private func didToggleReplies(_ toggle: UISwitch) {
|
||||
let myStoryThread: TSPrivateStoryThread! = SSKEnvironment.shared.databaseStorageRef.read { TSPrivateStoryThread.getMyStory(transaction: $0) }
|
||||
let myStoryThread: TSPrivateStoryThread = SSKEnvironment.shared.databaseStorageRef.read { TSPrivateStoryThread.getMyStory(transaction: $0)! }
|
||||
guard myStoryThread.allowsReplies != toggle.isOn else { return }
|
||||
SSKEnvironment.shared.databaseStorageRef.write { transaction in
|
||||
myStoryThread.updateWithAllowsReplies(toggle.isOn, updateStorageService: true, transaction: transaction)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user