Compare commits

...

16 Commits

Author SHA1 Message Date
Morgan Pretty 8839b3b108
Merge pull request #883 from mpretty-cyro/feature/drop-yap-database-support
Remove YapDatabase Dependency
2 months ago
Morgan Pretty e1bb6de7d6 Merge remote-tracking branch 'upstream/dev' into feature/drop-yap-database-support
# Conflicts:
#	Podfile.lock
#	SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift
3 months ago
Morgan Pretty 15e8c9bd09 Merge remote-tracking branch 'RyanFork/disappearing-message-redesign' into feature/drop-yap-database-support 6 months ago
Morgan Pretty 60684bc977 Merge remote-tracking branch 'RyanFork/disappearing-message-redesign' into feature/drop-yap-database-support 6 months ago
Morgan Pretty 75ba1edf73 Merge branch 'disappearing-message-redesign' into feature/drop-yap-database-support 7 months ago
Morgan Pretty 4093d812b5 Merge branch 'disappearing-message-redesign' into feature/drop-yap-database-support 8 months ago
Morgan Pretty ddc643a0a1 Merge branch 'disappearing-message-redesign' into feature/drop-yap-database-support 8 months ago
Morgan Pretty ab40fcdedf Merge branch 'disappearing-message-redesign' into feature/drop-yap-database-support 8 months ago
Morgan Pretty e43ec1db43 Removed another random deleted file reference from the pbxproj 8 months ago
Morgan Pretty 88fd134228 Removed some invalid references 8 months ago
Morgan Pretty 18b296bcd8 Merge branch 'disappearing-message-redesign' into feature/drop-yap-database-support
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	Session/Meta/AppDelegate.swift
#	Session/Meta/Translations/de.lproj/Localizable.strings
#	Session/Meta/Translations/es-ES.lproj/Localizable.strings
#	Session/Meta/Translations/fi.lproj/Localizable.strings
#	Session/Meta/Translations/fr.lproj/Localizable.strings
#	Session/Meta/Translations/it.lproj/Localizable.strings
#	Session/Meta/Translations/ja.lproj/Localizable.strings
#	Session/Meta/Translations/pl.lproj/Localizable.strings
#	Session/Meta/Translations/pt-BR.lproj/Localizable.strings
#	Session/Meta/Translations/ru.lproj/Localizable.strings
#	Session/Meta/Translations/sk.lproj/Localizable.strings
#	Session/Meta/Translations/zh-CN.lproj/Localizable.strings
#	Session/Meta/Translations/zh-TW.lproj/Localizable.strings
#	SessionMessagingKit/Database/LegacyDatabase/SMKLegacy.swift
#	SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift
#	SessionMessagingKit/Messages/Control Messages/ConfigurationMessage.swift
#	SessionSnodeKit/Database/LegacyDatabase/SSKLegacy.swift
#	SessionSnodeKit/Database/Migrations/_003_YDBToGRDBMigration.swift
#	SessionUtilitiesKit/Database/LegacyDatabase/SUKLegacy.swift
#	SessionUtilitiesKit/Database/Migrations/_003_YDBToGRDBMigration.swift
8 months ago
Morgan Pretty 3e4a2013d3 Fixed a bug where the 'migrationNoLongerSupported' would be thrown for new accounts 9 months ago
Morgan Pretty a4ade7fdb4 Merge remote-tracking branch 'upstream/dev' into feature/drop-yap-database-support 9 months ago
Morgan Pretty a6a545710d Merge remote-tracking branch 'upstream/dev' into feature/drop-yap-database-support 9 months ago
Morgan Pretty e1950ed0b5 Merge branch 'dev' into feature/drop-yap-database-support
# Conflicts:
#	Session.xcodeproj/project.pbxproj
#	SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift
#	SessionUtilitiesKit/Database/Storage.swift
9 months ago
Morgan Pretty 50bc2f9a5c Removed YapDatabase and the migrations
Removed the YapDatabase CocoaPod
Removed logic to migrate from YapDatabase to GRDB
Removed the logic to check for legacy config messages during onboarding
Added a database error for when a migration is no longer supported
10 months ago

@ -13,9 +13,6 @@ abstract_target 'GlobalDependencies' do
# FIXME: Would be nice to migrate from CocoaPods to SwiftPackageManager (should allow us to speed up build time), haven't gone through all of the dependencies but currently unfortunately SQLCipher doesn't support SPM (for more info see: https://github.com/sqlcipher/sqlcipher/issues/371)
pod 'SQLCipher', '~> 4.5.3'
# FIXME: We want to remove this once it's been long enough since the migration to GRDB
pod 'YapDatabase/SQLCipher', :git => 'https://github.com/oxen-io/session-ios-yap-database.git', branch: 'signal-release'
pod 'WebRTC-lib'
target 'Session' do

@ -45,68 +45,6 @@ PODS:
- SQLCipher/common
- SwiftProtobuf (1.5.0)
- WebRTC-lib (114.0.0)
- YapDatabase/SQLCipher (3.1.1):
- YapDatabase/SQLCipher/Core (= 3.1.1)
- YapDatabase/SQLCipher/Extensions (= 3.1.1)
- YapDatabase/SQLCipher/Core (3.1.1):
- CocoaLumberjack
- SQLCipher (>= 3.4.0)
- YapDatabase/SQLCipher/Extensions (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/ActionManager (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/AutoView (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/CloudCore (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/CloudKit (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/ConnectionPool (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/FilteredView (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/FullTextSearch (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/Hooks (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/ManualView (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/Relationships (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/RTreeIndex (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/SearchResultsView (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/View (= 3.1.1)
- YapDatabase/SQLCipher/Extensions/ActionManager (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/AutoView
- YapDatabase/SQLCipher/Extensions/AutoView (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/View
- YapDatabase/SQLCipher/Extensions/CloudCore (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/CloudKit (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/ConnectionPool (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/FilteredView (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/View
- YapDatabase/SQLCipher/Extensions/FullTextSearch (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/Hooks (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/ManualView (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/View
- YapDatabase/SQLCipher/Extensions/Relationships (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/RTreeIndex (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/SearchResultsView (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/AutoView
- YapDatabase/SQLCipher/Extensions/FullTextSearch
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (3.1.1):
- YapDatabase/SQLCipher/Core
- YapDatabase/SQLCipher/Extensions/View (3.1.1):
- YapDatabase/SQLCipher/Core
- YYImage/Core (1.0.4)
- YYImage/libwebp (1.0.4):
- libwebp
@ -127,7 +65,6 @@ DEPENDENCIES:
- SQLCipher (~> 4.5.3)
- SwiftProtobuf (~> 1.5.0)
- WebRTC-lib
- YapDatabase/SQLCipher (from `https://github.com/oxen-io/session-ios-yap-database.git`, branch `signal-release`)
- YYImage/libwebp (from `https://github.com/signalapp/YYImage`)
SPEC REPOS:
@ -157,9 +94,6 @@ EXTERNAL SOURCES:
Sodium:
:branch: session-build
:git: https://github.com/oxen-io/session-ios-swift-sodium.git
YapDatabase:
:branch: signal-release
:git: https://github.com/oxen-io/session-ios-yap-database.git
YYImage:
:git: https://github.com/signalapp/YYImage
@ -173,9 +107,6 @@ CHECKOUT OPTIONS:
Sodium:
:commit: 4ecfe2ddfd75e7b396c57975b4163e5c8cf4d5cc
:git: https://github.com/oxen-io/session-ios-swift-sodium.git
YapDatabase:
:commit: d84069e25e12a16ab4422e5258127a04b70489ad
:git: https://github.com/oxen-io/session-ios-yap-database.git
YYImage:
:commit: 62a4cede20bcf31da73d18163408e46a92f171c6
:git: https://github.com/signalapp/YYImage
@ -198,9 +129,8 @@ SPEC CHECKSUMS:
SQLCipher: 57fa9f863fa4a3ed9dd3c90ace52315db8c0fdca
SwiftProtobuf: 241400280f912735c1e1b9fe675fdd2c6c4d42e2
WebRTC-lib: d83df8976fa608b980f1d85796b3de66d60a1953
YapDatabase: b418a4baa6906e8028748938f9159807fd039af4
YYImage: f1ddd15ac032a58b78bbed1e012b50302d318331
PODFILE CHECKSUM: f56c28baefe3077effcb3a2ea5941b52c4cc6e86
PODFILE CHECKSUM: 4e88e94d595188c412f739792fb78e0e92a8be12
COCOAPODS: 1.14.3

@ -497,12 +497,10 @@
FD16AB5F2A1DD98F0083D849 /* ProfilePictureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38EF2A4255B6D93007E1867 /* ProfilePictureView.swift */; };
FD16AB612A1DD9B60083D849 /* ProfilePictureView+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD16AB602A1DD9B60083D849 /* ProfilePictureView+Convenience.swift */; };
FD17D79927F40AB800122BE0 /* _003_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79827F40AB800122BE0 /* _003_YDBToGRDBMigration.swift */; };
FD17D79C27F40B2E00122BE0 /* SMKLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79B27F40B2E00122BE0 /* SMKLegacy.swift */; };
FD17D7A027F40CC800122BE0 /* _001_InitialSetupMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */; };
FD17D7A127F40D2500122BE0 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F527EAD44C00FF65E7 /* Storage.swift */; };
FD17D7A227F40F0500122BE0 /* _001_InitialSetupMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79527F3E04600122BE0 /* _001_InitialSetupMigration.swift */; };
FD17D7A427F40F8100122BE0 /* _003_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A327F40F8100122BE0 /* _003_YDBToGRDBMigration.swift */; };
FD17D7A727F41AF000122BE0 /* SSKLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A627F41AF000122BE0 /* SSKLegacy.swift */; };
FD17D7AA27F41BF500122BE0 /* SnodeSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A927F41BF500122BE0 /* SnodeSet.swift */; };
FD17D7AE27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7AD27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift */; };
FD17D7B327F51E5B00122BE0 /* SSKSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7B227F51E5B00122BE0 /* SSKSetting.swift */; };
@ -517,7 +515,6 @@
FD17D7CD27F546FF00122BE0 /* Setting.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7CC27F546FF00122BE0 /* Setting.swift */; };
FD17D7E527F6A09900122BE0 /* Identity.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E427F6A09900122BE0 /* Identity.swift */; };
FD17D7E727F6A16700122BE0 /* _003_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E627F6A16700122BE0 /* _003_YDBToGRDBMigration.swift */; };
FD17D7EA27F6A1C600122BE0 /* SUKLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E927F6A1C600122BE0 /* SUKLegacy.swift */; };
FD19363F2ACA66DE004BCF0F /* DatabaseSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD19363E2ACA66DE004BCF0F /* DatabaseSpec.swift */; };
FD1936412ACA7BD8004BCF0F /* Result+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD1936402ACA7BD8004BCF0F /* Result+Utilities.swift */; };
FD1A94FB2900D1C2000D73D3 /* PersistableRecord+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD1A94FA2900D1C2000D73D3 /* PersistableRecord+Utilities.swift */; };
@ -560,7 +557,7 @@
FD245C59285065FC00B966DD /* ControlMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2A7702553A41E00C340D1 /* ControlMessage.swift */; };
FD245C5A2850660100B966DD /* LinkPreviewDraft.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBA8255A581500E217F9 /* LinkPreviewDraft.swift */; };
FD245C5B2850660500B966DD /* ReadReceipt.swift in Sources */ = {isa = PBXBuildFile; fileRef = C300A5BC2554B00D00555489 /* ReadReceipt.swift */; };
FD245C5C2850660A00B966DD /* ConfigurationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DA9C0625AE7396008F7C7E /* ConfigurationMessage.swift */; };
FD245C5C2850660A00B966DD /* LegacyConfigurationMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DA9C0625AE7396008F7C7E /* LegacyConfigurationMessage.swift */; };
FD245C5D2850660F00B966DD /* OWSAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF2F7255B6DBC007E1867 /* OWSAudioPlayer.m */; };
FD245C5F2850662200B966DD /* OWSWindowManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF306255B6DBE007E1867 /* OWSWindowManager.m */; };
FD245C632850664600B966DD /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD245C612850664300B966DD /* Configuration.swift */; };
@ -1595,7 +1592,7 @@
C3CA3ABD255CDB0D00F4C6D4 /* portuguese.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = portuguese.txt; sourceTree = "<group>"; };
C3CA3AC7255CDB2900F4C6D4 /* spanish.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = spanish.txt; sourceTree = "<group>"; };
C3D0972A2510499C00F6E3E4 /* BackgroundPoller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundPoller.swift; sourceTree = "<group>"; };
C3DA9C0625AE7396008F7C7E /* ConfigurationMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationMessage.swift; sourceTree = "<group>"; };
C3DA9C0625AE7396008F7C7E /* LegacyConfigurationMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyConfigurationMessage.swift; sourceTree = "<group>"; };
C3DAB3232480CB2A00725F25 /* SRCopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCopyableLabel.swift; sourceTree = "<group>"; };
C3DB66AB260ACA42001EFC55 /* OpenGroupManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupManager.swift; sourceTree = "<group>"; };
C3DB66C2260ACCE6001EFC55 /* OpenGroupPoller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenGroupPoller.swift; sourceTree = "<group>"; };
@ -1666,10 +1663,8 @@
FD16AB602A1DD9B60083D849 /* ProfilePictureView+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfilePictureView+Convenience.swift"; sourceTree = "<group>"; };
FD17D79527F3E04600122BE0 /* _001_InitialSetupMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _001_InitialSetupMigration.swift; sourceTree = "<group>"; };
FD17D79827F40AB800122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = "<group>"; };
FD17D79B27F40B2E00122BE0 /* SMKLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMKLegacy.swift; sourceTree = "<group>"; };
FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _001_InitialSetupMigration.swift; sourceTree = "<group>"; };
FD17D7A327F40F8100122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = "<group>"; };
FD17D7A627F41AF000122BE0 /* SSKLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKLegacy.swift; sourceTree = "<group>"; };
FD17D7A927F41BF500122BE0 /* SnodeSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeSet.swift; sourceTree = "<group>"; };
FD17D7AD27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeReceivedMessageInfo.swift; sourceTree = "<group>"; };
FD17D7AF27F4225C00122BE0 /* Set+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Set+Utilities.swift"; sourceTree = "<group>"; };
@ -1685,7 +1680,6 @@
FD17D7CC27F546FF00122BE0 /* Setting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Setting.swift; sourceTree = "<group>"; };
FD17D7E427F6A09900122BE0 /* Identity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Identity.swift; sourceTree = "<group>"; };
FD17D7E627F6A16700122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = "<group>"; };
FD17D7E927F6A1C600122BE0 /* SUKLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SUKLegacy.swift; sourceTree = "<group>"; };
FD19363E2ACA66DE004BCF0F /* DatabaseSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseSpec.swift; sourceTree = "<group>"; };
FD1936402ACA7BD8004BCF0F /* Result+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Result+Utilities.swift"; sourceTree = "<group>"; };
FD1A94FA2900D1C2000D73D3 /* PersistableRecord+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PersistableRecord+Utilities.swift"; sourceTree = "<group>"; };
@ -2596,7 +2590,6 @@
B8A582AB258C64E800AFD84C /* Database */ = {
isa = PBXGroup;
children = (
FD17D7E827F6A1B800122BE0 /* LegacyDatabase */,
FD17D7C827F546CE00122BE0 /* Migrations */,
FD17D7CB27F546F500122BE0 /* Models */,
FD17D7B427F51E6700122BE0 /* Types */,
@ -2810,7 +2803,7 @@
B8DE1FB526C22FCB0079C9CE /* CallMessage.swift */,
C34A977325A3E34A00852C71 /* ClosedGroupControlMessage.swift */,
FD8ECF8A2935DB4B00C0D1BB /* SharedConfigMessage.swift */,
C3DA9C0625AE7396008F7C7E /* ConfigurationMessage.swift */,
C3DA9C0625AE7396008F7C7E /* LegacyConfigurationMessage.swift */,
B8F5F60225EDE16F003BF8D4 /* DataExtractionNotification.swift */,
C300A5E62554B07300555489 /* ExpirationTimerUpdate.swift */,
7B93D06F27CF194000811CB6 /* MessageRequestResponse.swift */,
@ -2921,7 +2914,6 @@
C32C5BCB256DC818003C73A2 /* Database */ = {
isa = PBXGroup;
children = (
FD17D79A27F40ADA00122BE0 /* LegacyDatabase */,
FD17D79427F3E03300122BE0 /* Migrations */,
FD09796C27FA6C8B00936362 /* Models */,
);
@ -3694,18 +3686,9 @@
path = Migrations;
sourceTree = "<group>";
};
FD17D79A27F40ADA00122BE0 /* LegacyDatabase */ = {
isa = PBXGroup;
children = (
FD17D79B27F40B2E00122BE0 /* SMKLegacy.swift */,
);
path = LegacyDatabase;
sourceTree = "<group>";
};
FD17D79D27F40CAA00122BE0 /* Database */ = {
isa = PBXGroup;
children = (
FD17D7A527F41ADE00122BE0 /* LegacyDatabase */,
FD17D79E27F40CC000122BE0 /* Migrations */,
FD17D7A827F41BE300122BE0 /* Models */,
FD17D7B127F51E2B00122BE0 /* Types */,
@ -3725,14 +3708,6 @@
path = Migrations;
sourceTree = "<group>";
};
FD17D7A527F41ADE00122BE0 /* LegacyDatabase */ = {
isa = PBXGroup;
children = (
FD17D7A627F41AF000122BE0 /* SSKLegacy.swift */,
);
path = LegacyDatabase;
sourceTree = "<group>";
};
FD17D7A827F41BE300122BE0 /* Models */ = {
isa = PBXGroup;
children = (
@ -3805,14 +3780,6 @@
path = Models;
sourceTree = "<group>";
};
FD17D7E827F6A1B800122BE0 /* LegacyDatabase */ = {
isa = PBXGroup;
children = (
FD17D7E927F6A1C600122BE0 /* SUKLegacy.swift */,
);
path = LegacyDatabase;
sourceTree = "<group>";
};
FD19363D2ACA66CF004BCF0F /* Database */ = {
isa = PBXGroup;
children = (
@ -5826,7 +5793,6 @@
FDF848ED29405E4F007DCAE5 /* Notification+OnionRequestAPI.swift in Sources */,
FDF848CD29405C5B007DCAE5 /* GetNetworkTimestampResponse.swift in Sources */,
FDF848DA29405C5B007DCAE5 /* GetMessagesResponse.swift in Sources */,
FD17D7A727F41AF000122BE0 /* SSKLegacy.swift in Sources */,
FD39353628F7C3390084DADA /* _004_FlagMessageHashAsDeletedOrInvalid.swift in Sources */,
FDF8489429405C1B007DCAE5 /* SnodeAPI.swift in Sources */,
FDF848C829405C5B007DCAE5 /* ONSResolveRequest.swift in Sources */,
@ -5859,7 +5825,6 @@
C3BBE0A82554D4DE0050F1E3 /* JSON.swift in Sources */,
FD17D7C127F5200100122BE0 /* TypedTableDefinition.swift in Sources */,
FD23CE1B2A651E6D0000B97C /* NetworkType.swift in Sources */,
FD17D7EA27F6A1C600122BE0 /* SUKLegacy.swift in Sources */,
FDA8EB10280F8238002B68E5 /* Codable+Utilities.swift in Sources */,
FDBB25E32988B13800F1508E /* _004_AddJobPriority.swift in Sources */,
C352A36D2557858E00338F3E /* NSTimer+Proxying.m in Sources */,
@ -6142,7 +6107,7 @@
C3DB66C3260ACCE6001EFC55 /* OpenGroupPoller.swift in Sources */,
FD716E722850647600C96BF4 /* Data+Utilities.swift in Sources */,
FD368A6829DE8F9C000DBF1E /* _012_AddFTSIfNeeded.swift in Sources */,
FD245C5C2850660A00B966DD /* ConfigurationMessage.swift in Sources */,
FD245C5C2850660A00B966DD /* LegacyConfigurationMessage.swift in Sources */,
FD5C7301284F0F7A0029977D /* MessageReceiver+UnsendRequests.swift in Sources */,
C3C2A75F2553A3C500C340D1 /* VisibleMessage+LinkPreview.swift in Sources */,
FD245C642850664F00B966DD /* Threading.swift in Sources */,
@ -6168,7 +6133,6 @@
FD09798B27FD1CFE00936362 /* Capability.swift in Sources */,
C3BBE0C72554F1570050F1E3 /* FixedWidthInteger+BigEndian.swift in Sources */,
FD1D732A2A85AA2000E3F410 /* Setting+Utilities.swift in Sources */,
FD17D79C27F40B2E00122BE0 /* SMKLegacy.swift in Sources */,
FD09798127FCFEE800936362 /* SessionThread.swift in Sources */,
FD09C5EA282A1BB2000CE219 /* ThreadTypingIndicator.swift in Sources */,
FDF0B75E280AAF35004C14C5 /* Preferences.swift in Sources */,

@ -429,18 +429,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// Offer the 'Restore' option if it was a migration error
case .databaseError:
alert.addAction(UIAlertAction(title: "vc_restore_title".localized(), style: .destructive) { _ in
if SUKLegacy.hasLegacyDatabaseFile {
// Remove the legacy database and any message hashes that have been migrated to the new DB
try? SUKLegacy.deleteLegacyDatabaseFilesAndKey()
Storage.shared.write { db in
try SnodeReceivedMessageInfo.deleteAll(db)
}
}
else {
// If we don't have a legacy database then reset the current database for a clean migration
Storage.resetForCleanMigration()
}
// Reset the current database for a clean migration
Storage.resetForCleanMigration()
// Hide the top banner if there was one
TopBannerController.hide()
@ -890,7 +880,8 @@ private enum StartupError: Error {
switch self {
case .databaseError(StorageError.startupFailed), .databaseError(DatabaseError.SQLITE_LOCKED):
return "Database startup failed"
case .databaseError(StorageError.migrationNoLongerSupported): return "Unsupported version"
case .failedToRestore: return "Failed to restore"
case .databaseError: return "Database error"
case .startupTimeout: return "Startup timeout"
@ -901,7 +892,10 @@ private enum StartupError: Error {
switch self {
case .databaseError(StorageError.startupFailed), .databaseError(DatabaseError.SQLITE_LOCKED):
return "DATABASE_STARTUP_FAILED".localized()
case .databaseError(StorageError.migrationNoLongerSupported):
return "DATABASE_UNSUPPORTED_MIGRATION".localized()
case .failedToRestore: return "DATABASE_RESTORE_FAILED".localized()
case .databaseError: return "DATABASE_MIGRATION_FAILED".localized()
case .startupTimeout: return "APP_STARTUP_TIMEOUT".localized()

@ -150,31 +150,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Software License Agreement (BSD License)
Copyright (c) 2013, yap.TV Inc.
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Neither the name of yap.TV nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of yap.TV Inc.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</string>
<key>Title</key>
<string>YapDatabase</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string> Apache License

@ -33,7 +33,7 @@ enum Onboarding {
let userPublicKey: String = getUserHexEncodedPublicKey(using: dependencies)
return SnodeAPI.getSwarm(for: userPublicKey)
.tryFlatMapWithRandomSnode { snode -> AnyPublisher<Void, Error> in
.tryFlatMapWithRandomSnode { snode -> AnyPublisher<[Message], Error> in
CurrentUserPoller
.poll(
namespaces: [.configUserProfile],
@ -44,70 +44,9 @@ enum Onboarding {
calledFromBackgroundPoller: true,
isBackgroundPollValid: { true }
)
.tryFlatMap { receivedMessageTypes -> AnyPublisher<Void, Error> in
// FIXME: Remove this entire 'tryFlatMap' once the updated user config has been released for long enough
guard
receivedMessageTypes.isEmpty,
requestId == profileNameRetrievalIdentifier.wrappedValue
else {
return Just(())
.setFailureType(to: Error.self)
.eraseToAnyPublisher()
}
SNLog("Onboarding failed to retrieve user config, checking for legacy config")
return CurrentUserPoller
.poll(
namespaces: [.default],
from: snode,
for: userPublicKey,
// Note: These values mean the received messages will be
// processed immediately rather than async as part of a Job
calledFromBackgroundPoller: true,
isBackgroundPollValid: { true }
)
.tryMap { receivedMessageTypes -> Void in
guard
let message: ConfigurationMessage = receivedMessageTypes
.last(where: { $0 is ConfigurationMessage })
.asType(ConfigurationMessage.self),
let displayName: String = message.displayName,
requestId == profileNameRetrievalIdentifier.wrappedValue
else { return () }
// Handle user profile changes
Storage.shared.write { db in
try ProfileManager.updateProfileIfNeeded(
db,
publicKey: userPublicKey,
name: displayName,
avatarUpdate: {
guard
let profilePictureUrl: String = message.profilePictureUrl,
let profileKey: Data = message.profileKey
else { return .none }
return .updateTo(
url: profilePictureUrl,
key: profileKey,
fileName: nil
)
}(),
sentTimestamp: TimeInterval((message.sentTimestamp ?? 0) / 1000),
calledFromConfigHandling: false,
using: dependencies
)
}
return ()
}
.eraseToAnyPublisher()
}
}
.map { _ -> String? in
guard requestId == profileNameRetrievalIdentifier.wrappedValue else {
return nil
}
guard requestId == profileNameRetrievalIdentifier.wrappedValue else { return nil }
return Storage.shared.read { db in
try Profile

File diff suppressed because it is too large Load Diff

@ -5,7 +5,7 @@ import GRDB
import SessionUtilitiesKit
import SessionSnodeKit
/// This migration removes the legacy YapDatabase files
/// This migration used to remove the legacy YapDatabase files (the old logic has been removed and is no longer supported so it now does nothing)
enum _004_RemoveLegacyYDB: Migration {
static let target: TargetMigrations.Identifier = .messagingKit
static let identifier: String = "RemoveLegacyYDB" // stringlint:disable
@ -15,7 +15,6 @@ enum _004_RemoveLegacyYDB: Migration {
static let createdOrAlteredTables: [(TableRecord & FetchableRecord).Type] = []
static func migrate(_ db: Database) throws {
try? SUKLegacy.deleteLegacyDatabaseFilesAndKey()
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

@ -114,7 +114,7 @@ public struct ControlMessageProcessRecord: Codable, FetchableRecord, Persistable
case is ClosedGroupControlMessage: return .closedGroupControlMessage
case is DataExtractionNotification: return .dataExtractionNotification
case is ExpirationTimerUpdate: return .expirationTimerUpdate
case is ConfigurationMessage, is SharedConfigMessage: return .configurationMessage
case is LegacyConfigurationMessage, is SharedConfigMessage: return .configurationMessage
case is UnsendRequest: return .unsendRequest
case is MessageRequestResponse: return .messageRequestResponse
case is CallMessage: return .call

@ -1,85 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtilitiesKit
public final class ConfigurationMessage: ControlMessage {
private enum CodingKeys: String, CodingKey {
case displayName
case profilePictureUrl
case profileKey
}
public var displayName: String?
public var profilePictureUrl: String?
public var profileKey: Data?
public override var isSelfSendValid: Bool { true }
// MARK: - Initialization
public init(
displayName: String?,
profilePictureUrl: String?,
profileKey: Data?
) {
super.init()
self.displayName = displayName
self.profilePictureUrl = profilePictureUrl
self.profileKey = profileKey
}
// MARK: - Codable
required init(from decoder: Decoder) throws {
try super.init(from: decoder)
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
displayName = try? container.decode(String.self, forKey: .displayName)
profilePictureUrl = try? container.decode(String.self, forKey: .profilePictureUrl)
profileKey = try? container.decode(Data.self, forKey: .profileKey)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(displayName, forKey: .displayName)
try container.encodeIfPresent(profilePictureUrl, forKey: .profilePictureUrl)
try container.encodeIfPresent(profileKey, forKey: .profileKey)
}
// MARK: - Proto Conversion
public override class func fromProto(_ proto: SNProtoContent, sender: String) -> ConfigurationMessage? {
guard let configurationProto = proto.configurationMessage else { return nil }
let displayName = configurationProto.displayName
let profilePictureUrl = configurationProto.profilePicture
let profileKey = configurationProto.profileKey
return ConfigurationMessage(
displayName: displayName,
profilePictureUrl: profilePictureUrl,
profileKey: profileKey
)
}
public override func toProto(_ db: Database, threadId: String) -> SNProtoContent? { return nil }
// MARK: - Description
public var description: String {
"""
LegacyConfigurationMessage(
displayName: \(displayName ?? "null"),
profilePictureUrl: \(profilePictureUrl ?? "null"),
profileKey: \(profileKey?.toHexString() ?? "null")
)
"""
}
}

@ -0,0 +1,17 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
public final class LegacyConfigurationMessage: ControlMessage {
public override var isSelfSendValid: Bool { true }
public override class func fromProto(_ proto: SNProtoContent, sender: String) -> LegacyConfigurationMessage? {
guard proto.configurationMessage != nil else { return nil }
return LegacyConfigurationMessage()
}
public override func toProto(_ db: Database, threadId: String) -> SNProtoContent? { return nil }
public var description: String { "LegacyConfigurationMessage()" } // stringlint:disable
}

@ -111,7 +111,7 @@ public extension Message {
case closedGroupControlMessage
case dataExtractionNotification
case expirationTimerUpdate
case configurationMessage
case legacyConfigurationMessage = "configurationMessage"
case unsendRequest
case messageRequestResponse
case visibleMessage
@ -125,7 +125,7 @@ public extension Message {
case is ClosedGroupControlMessage: self = .closedGroupControlMessage
case is DataExtractionNotification: self = .dataExtractionNotification
case is ExpirationTimerUpdate: self = .expirationTimerUpdate
case is ConfigurationMessage: self = .configurationMessage
case is LegacyConfigurationMessage: self = .legacyConfigurationMessage
case is UnsendRequest: self = .unsendRequest
case is MessageRequestResponse: self = .messageRequestResponse
case is VisibleMessage: self = .visibleMessage
@ -142,7 +142,7 @@ public extension Message {
case .closedGroupControlMessage: return ClosedGroupControlMessage.self
case .dataExtractionNotification: return DataExtractionNotification.self
case .expirationTimerUpdate: return ExpirationTimerUpdate.self
case .configurationMessage: return ConfigurationMessage.self
case .legacyConfigurationMessage: return LegacyConfigurationMessage.self
case .unsendRequest: return UnsendRequest.self
case .messageRequestResponse: return MessageRequestResponse.self
case .visibleMessage: return VisibleMessage.self
@ -163,7 +163,10 @@ public extension Message {
return try container.decode(DataExtractionNotification.self, forKey: key)
case .expirationTimerUpdate: return try container.decode(ExpirationTimerUpdate.self, forKey: key)
case .configurationMessage: return try container.decode(ConfigurationMessage.self, forKey: key)
case .legacyConfigurationMessage:
return try container.decode(LegacyConfigurationMessage.self, forKey: key)
case .unsendRequest: return try container.decode(UnsendRequest.self, forKey: key)
case .messageRequestResponse: return try container.decode(MessageRequestResponse.self, forKey: key)
case .visibleMessage: return try container.decode(VisibleMessage.self, forKey: key)
@ -182,7 +185,7 @@ public extension Message {
.closedGroupControlMessage,
.dataExtractionNotification,
.expirationTimerUpdate,
.configurationMessage,
.legacyConfigurationMessage,
.unsendRequest,
.messageRequestResponse,
.visibleMessage,
@ -222,7 +225,7 @@ public extension Message {
switch message {
case is VisibleMessage: return true
case is ExpirationTimerUpdate: return true
case is ConfigurationMessage: return true
case is LegacyConfigurationMessage: return true
case is UnsendRequest: return true
case let controlMessage as ClosedGroupControlMessage:

@ -303,8 +303,8 @@ public enum MessageReceiver {
)
// SharedConfigMessages should be handled by the 'SharedUtil' instead of this
case is ConfigurationMessage: TopBannerController.show(warning: .outdatedUserConfig)
case is SharedConfigMessage: throw MessageReceiverError.invalidSharedConfigMessageHandling
case is LegacyConfigurationMessage: TopBannerController.show(warning: .outdatedUserConfig)
default: fatalError()
}
@ -323,7 +323,7 @@ public enum MessageReceiver {
switch message {
case is ReadReceipt: break
case is TypingIndicator: break
case is ConfigurationMessage: break
case is LegacyConfigurationMessage: break
case is UnsendRequest: break
case let message as ClosedGroupControlMessage:

@ -1,68 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
//
// stringlint:disable
import Foundation
public enum SSKLegacy {
// MARK: - Collections and Keys
internal static let swarmCollectionPrefix = "LokiSwarmCollection-"
internal static let lastSnodePoolRefreshDateKey = "lastSnodePoolRefreshDate"
internal static let snodePoolCollection = "LokiSnodePoolCollection"
internal static let onionRequestPathCollection = "LokiOnionRequestPathCollection"
internal static let lastSnodePoolRefreshDateCollection = "LokiLastSnodePoolRefreshDateCollection"
internal static let lastMessageHashCollection = "LokiLastMessageHashCollection"
internal static let receivedMessagesCollection = "LokiReceivedMessagesCollection"
// MARK: - Types
public typealias LegacyOnionRequestAPIPath = [Snode]
@objc(Snode)
public final class Snode: NSObject, NSCoding {
public let address: String
public let port: UInt16
public let publicKeySet: KeySet
// MARK: - Nested Types
public struct KeySet {
public let ed25519Key: String
public let x25519Key: String
}
// MARK: - NSCoding
public init?(coder: NSCoder) {
address = coder.decodeObject(forKey: "address") as! String
port = coder.decodeObject(forKey: "port") as! UInt16
guard
let idKey = coder.decodeObject(forKey: "idKey") as? String,
let encryptionKey = coder.decodeObject(forKey: "encryptionKey") as? String
else { return nil }
publicKeySet = KeySet(ed25519Key: idKey, x25519Key: encryptionKey)
super.init()
}
public func encode(with coder: NSCoder) {
fatalError("encode(with:) should never be called for legacy types")
}
// Note: The 'isEqual' and 'hash' overrides are both needed to ensure the migration
// doesn't try to insert duplicate SNode entries into the new database (which would
// result in unique key constraint violations)
override public func isEqual(_ other: Any?) -> Bool {
guard let other = other as? Snode else { return false }
return address == other.address && port == other.port
}
override public var hash: Int {
return address.hashValue ^ port.hashValue
}
}
}

@ -1,218 +1,24 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
//
// stringlint:disable
import Foundation
import GRDB
import YapDatabase
import SessionUtilitiesKit
enum _003_YDBToGRDBMigration: Migration {
static let target: TargetMigrations.Identifier = .snodeKit
static let identifier: String = "YDBToGRDBMigration"
static let identifier: String = "YDBToGRDBMigration" // stringlint:disable
static let needsConfigSync: Bool = false
static let fetchedTables: [(TableRecord & FetchableRecord).Type] = []
static let minExpectedRunDuration: TimeInterval = 0.1
static let fetchedTables: [(TableRecord & FetchableRecord).Type] = [Identity.self]
static let createdOrAlteredTables: [(TableRecord & FetchableRecord).Type] = []
/// This migration can take a while if it's a very large database or there are lots of closed groups (want this to account
/// for about 10% of the progress bar so we intentionally have a higher `minExpectedRunDuration` so show more
/// progress during the migration)
static let minExpectedRunDuration: TimeInterval = 2.0
static func migrate(_ db: Database) throws {
guard let dbConnection: YapDatabaseConnection = SUKLegacy.newDatabaseConnection() else {
SNLogNotTests("[Migration Warning] No legacy database, skipping \(target.key(with: self))")
return
}
// MARK: - Read from Legacy Database
// Note: Want to exclude the Snode's we already added from the 'onionRequestPathResult'
var snodeResult: Set<SSKLegacy.Snode> = []
var snodeSetResult: [String: Set<SSKLegacy.Snode>] = [:]
var lastSnodePoolRefreshDate: Date? = nil
var lastMessageResults: [String: (hash: String, json: JSON)] = [:]
var receivedMessageResults: [String: Set<String>] = [:]
// Map the Legacy types for the NSKeyedUnarchiver
NSKeyedUnarchiver.setClass(
SSKLegacy.Snode.self,
forClassName: "SessionSnodeKit.Snode"
)
dbConnection.read { transaction in
// MARK: --lastSnodePoolRefreshDate
lastSnodePoolRefreshDate = transaction.object(
forKey: SSKLegacy.lastSnodePoolRefreshDateKey,
inCollection: SSKLegacy.lastSnodePoolRefreshDateCollection
) as? Date
// MARK: --OnionRequestPaths
if
let path0Snode0 = transaction.object(forKey: "0-0", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode,
let path0Snode1 = transaction.object(forKey: "0-1", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode,
let path0Snode2 = transaction.object(forKey: "0-2", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode
{
snodeResult.insert(path0Snode0)
snodeResult.insert(path0Snode1)
snodeResult.insert(path0Snode2)
snodeSetResult["\(SnodeSet.onionRequestPathPrefix)0"] = [ path0Snode0, path0Snode1, path0Snode2 ]
if
let path1Snode0 = transaction.object(forKey: "1-0", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode,
let path1Snode1 = transaction.object(forKey: "1-1", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode,
let path1Snode2 = transaction.object(forKey: "1-2", inCollection: SSKLegacy.onionRequestPathCollection) as? SSKLegacy.Snode
{
snodeResult.insert(path1Snode0)
snodeResult.insert(path1Snode1)
snodeResult.insert(path1Snode2)
snodeSetResult["\(SnodeSet.onionRequestPathPrefix)1"] = [ path1Snode0, path1Snode1, path1Snode2 ]
}
}
Storage.update(progress: 0.02, for: self, in: target)
// MARK: --SnodePool
transaction.enumerateKeysAndObjects(inCollection: SSKLegacy.snodePoolCollection) { _, object, _ in
guard let snode = object as? SSKLegacy.Snode else { return }
snodeResult.insert(snode)
}
// MARK: --Swarms
/// **Note:** There is no index on the collection column so unfortunately it takes the same amount of time to enumerate through all
/// collections as it does to just get the count of collections, due to this, if the database is very large, importing thecollections can be
/// very slow (~15s with 2,000,000 rows) - we want to show some kind of progress while enumerating so the below code creates a
/// very rought guess of the number of collections based on the file size of the database (this shouldn't affect most users at all)
let roughMbPerCollection: CGFloat = 2.5
let oldDatabaseSizeBytes: CGFloat = (try? FileManager.default
.attributesOfItem(atPath: SUKLegacy.legacyDatabaseFilepath)[.size]
.asType(CGFloat.self))
.defaulting(to: 0)
let roughNumCollections: CGFloat = (((oldDatabaseSizeBytes / 1024) / 1024) / roughMbPerCollection)
let startProgress: CGFloat = 0.02
let swarmCompleteProgress: CGFloat = 0.90
var swarmCollections: Set<String> = []
var collectionIndex: CGFloat = 0
transaction.enumerateCollections { collectionName, _ in
if collectionName.starts(with: SSKLegacy.swarmCollectionPrefix) {
swarmCollections.insert(collectionName.substring(from: SSKLegacy.swarmCollectionPrefix.count))
}
collectionIndex += 1
Storage.update(
progress: min(
swarmCompleteProgress,
((collectionIndex / roughNumCollections) * (swarmCompleteProgress - startProgress))
),
for: self,
in: target
)
}
Storage.update(progress: swarmCompleteProgress, for: self, in: target)
for swarmCollection in swarmCollections {
let collection: String = "\(SSKLegacy.swarmCollectionPrefix)\(swarmCollection)"
transaction.enumerateKeysAndObjects(inCollection: collection) { _, object, _ in
guard let snode = object as? SSKLegacy.Snode else { return }
snodeResult.insert(snode)
snodeSetResult[swarmCollection] = (snodeSetResult[swarmCollection] ?? Set()).inserting(snode)
}
}
Storage.update(progress: 0.92, for: self, in: target)
// MARK: --Received message hashes
transaction.enumerateKeysAndObjects(inCollection: SSKLegacy.receivedMessagesCollection) { key, object, _ in
guard let hashSet = object as? Set<String> else { return }
receivedMessageResults[key] = hashSet
}
Storage.update(progress: 0.93, for: self, in: target)
// MARK: --Last message info
transaction.enumerateKeysAndObjects(inCollection: SSKLegacy.lastMessageHashCollection) { key, object, _ in
guard let lastMessageJson = object as? JSON else { return }
guard let lastMessageHash: String = lastMessageJson["hash"] as? String else { return }
// Note: We remove the value from 'receivedMessageResults' as we want to try and use
// it's actual 'expirationDate' value
lastMessageResults[key] = (lastMessageHash, lastMessageJson)
receivedMessageResults[key] = receivedMessageResults[key]?.removing(lastMessageHash)
}
Storage.update(progress: 0.94, for: self, in: target)
}
// MARK: - Insert into GRDB
try autoreleasepool {
// MARK: --lastSnodePoolRefreshDate
db[.lastSnodePoolRefreshDate] = lastSnodePoolRefreshDate
// MARK: --SnodePool
try snodeResult.forEach { legacySnode in
try Snode(
address: legacySnode.address,
port: legacySnode.port,
ed25519PublicKey: legacySnode.publicKeySet.ed25519Key,
x25519PublicKey: legacySnode.publicKeySet.x25519Key
).migrationSafeInsert(db)
}
Storage.update(progress: 0.96, for: self, in: target)
// MARK: --SnodeSets
try snodeSetResult.forEach { key, legacySnodeSet in
try legacySnodeSet.enumerated().forEach { nodeIndex, legacySnode in
// Note: In this case the 'nodeIndex' is irrelivant
try SnodeSet(
key: key,
nodeIndex: nodeIndex,
address: legacySnode.address,
port: legacySnode.port
).migrationSafeInsert(db)
}
}
Storage.update(progress: 0.98, for: self, in: target)
}
try autoreleasepool {
// MARK: --Received Messages
try receivedMessageResults.forEach { key, hashes in
try hashes.forEach { hash in
_ = try SnodeReceivedMessageInfo(
key: key,
hash: hash,
expirationDateMs: SnodeReceivedMessage.defaultExpirationSeconds
).migrationSafeInserted(db)
}
}
Storage.update(progress: 0.99, for: self, in: target)
// MARK: --Last Message Hash
try lastMessageResults.forEach { key, data in
let expirationDateMs: Int64 = ((data.json["expirationDate"] as? Int64) ?? 0)
_ = try SnodeReceivedMessageInfo(
key: key,
hash: data.hash,
expirationDateMs: (expirationDateMs > 0 ?
expirationDateMs :
SnodeReceivedMessage.defaultExpirationSeconds
)
).migrationSafeInserted(db)
}
}
guard
!SNUtilitiesKit.isRunningTests &&
Identity.userExists(db)
else { return Storage.update(progress: 1, for: self, in: target) }
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
SNLogNotTests("[Migration Error] Attempted to perform legacy migation")
throw StorageError.migrationNoLongerSupported
}
}

@ -2,7 +2,6 @@
import Foundation
import GRDB
import YapDatabase
import SessionUtilitiesKit
enum _004_FlagMessageHashAsDeletedOrInvalid: Migration {

@ -1,169 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
//
// stringlint:disable
import Foundation
import YapDatabase
public enum SUKLegacy {
// MARK: - YapDatabase
private static let keychainService = "TSKeyChainService"
private static let keychainDBCipherKeySpec = "OWSDatabaseCipherKeySpec"
private static let sqlCipherKeySpecLength = 48
private static var database: Atomic<YapDatabase>?
// MARK: - Collections and Keys
internal static let userAccountRegisteredNumberKey = "TSStorageRegisteredNumberKey"
internal static let userAccountCollection = "TSStorageUserAccountCollection"
internal static let identityKeyStoreSeedKey = "LKLokiSeed"
internal static let identityKeyStoreEd25519SecretKey = "LKED25519SecretKey"
internal static let identityKeyStoreEd25519PublicKey = "LKED25519PublicKey"
internal static let identityKeyStoreIdentityKey = "TSStorageManagerIdentityKeyStoreIdentityKey"
internal static let identityKeyStoreCollection = "TSStorageManagerIdentityKeyStoreCollection"
// MARK: - Database Functions
public static var legacyDatabaseFilepath: String {
let sharedDirUrl: URL = URL(fileURLWithPath: OWSFileSystem.appSharedDataDirectoryPath())
return sharedDirUrl
.appendingPathComponent("database")
.appendingPathComponent("Signal.sqlite")
.path
}
private static let legacyDatabaseDeserializer: YapDatabaseDeserializer = {
return { (collection: String, key: String, data: Data) -> Any in
/// **Note:** The old `init(forReadingWith:)` method has been deprecated with `init(forReadingFrom:)`
/// and Apple changed the default of `requiresSecureCoding` to be true, this results in some of the types from failing
/// to decode, as a result we need to set it to false here
let unarchiver: NSKeyedUnarchiver? = try? NSKeyedUnarchiver(forReadingFrom: data)
unarchiver?.requiresSecureCoding = false
guard !data.isEmpty, let result = unarchiver?.decodeObject(forKey: "root") else {
return UnknownDBObject()
}
return result
}
}()
public static var hasLegacyDatabaseFile: Bool {
return FileManager.default.fileExists(atPath: legacyDatabaseFilepath)
}
@discardableResult public static func loadDatabaseIfNeeded() -> Bool {
guard SUKLegacy.database == nil else { return true }
/// Ensure the databaseKeySpec exists
var maybeKeyData: Data? = try? SSKDefaultKeychainStorage.shared.data(
forService: keychainService,
key: keychainDBCipherKeySpec
)
defer { if maybeKeyData != nil { maybeKeyData!.resetBytes(in: 0..<maybeKeyData!.count) } }
guard maybeKeyData != nil, maybeKeyData?.count == sqlCipherKeySpecLength else { return false }
// Setup the database options
let options: YapDatabaseOptions = YapDatabaseOptions()
options.corruptAction = .fail
options.enableMultiProcessSupport = true
options.cipherUnencryptedHeaderLength = kSqliteHeaderLength // Needed for iOS to support SQLite writes
options.legacyCipherCompatibilityVersion = 3 // Old DB was SQLCipher V3
options.cipherKeySpecBlock = {
/// To avoid holding the keySpec in memory too long we load it as needed, since we have already confirmed
/// it's existence we can force-try here (the database will crash if it's invalid anyway)
var keySpec: Data = try! SSKDefaultKeychainStorage.shared.data(
forService: keychainService,
key: keychainDBCipherKeySpec
)
defer { keySpec.resetBytes(in: 0..<keySpec.count) }
return keySpec
}
let maybeDatabase: YapDatabase? = YapDatabase(
path: legacyDatabaseFilepath,
serializer: nil,
deserializer: legacyDatabaseDeserializer,
options: options
)
guard let database: YapDatabase = maybeDatabase else { return false }
// Store the database instance atomically
SUKLegacy.database = Atomic(database)
return true
}
public static func newDatabaseConnection() -> YapDatabaseConnection? {
SUKLegacy.loadDatabaseIfNeeded()
return self.database?.wrappedValue.newConnection()
}
public static func clearLegacyDatabaseInstance() {
self.database = nil
}
public static func deleteLegacyDatabaseFilesAndKey() throws {
OWSFileSystem.deleteFile(legacyDatabaseFilepath)
OWSFileSystem.deleteFile("\(legacyDatabaseFilepath)-shm")
OWSFileSystem.deleteFile("\(legacyDatabaseFilepath)-wal")
try SSKDefaultKeychainStorage.shared.remove(service: keychainService, key: keychainDBCipherKeySpec)
}
// MARK: - UnknownDBObject
@objc(LegacyUnknownDBObject)
public class UnknownDBObject: NSObject, NSCoding {
override public init() {}
public required init?(coder: NSCoder) {}
public func encode(with coder: NSCoder) { fatalError("Shouldn't be encoding this type") }
}
// MARK: - LagacyKeyPair
@objc(LegacyKeyPair)
public class KeyPair: NSObject, NSCoding {
private static let keyLength: Int = 32
private static let publicKeyKey: String = "TSECKeyPairPublicKey"
private static let privateKeyKey: String = "TSECKeyPairPrivateKey"
public let publicKey: Data
public let privateKey: Data
public init(
publicKeyData: Data,
privateKeyData: Data
) {
publicKey = publicKeyData
privateKey = privateKeyData
}
public required init?(coder: NSCoder) {
var pubKeyLength: Int = 0
var privKeyLength: Int = 0
guard
let pubKeyBytes: UnsafePointer<UInt8> = coder.decodeBytes(forKey: KeyPair.publicKeyKey, returnedLength: &pubKeyLength),
let privateKeyBytes: UnsafePointer<UInt8> = coder.decodeBytes(forKey: KeyPair.privateKeyKey, returnedLength: &privKeyLength),
pubKeyLength == KeyPair.keyLength,
privKeyLength == KeyPair.keyLength
else {
// Fail if the keys aren't the correct length
return nil
}
publicKey = Data(bytes: pubKeyBytes, count: pubKeyLength)
privateKey = Data(bytes: privateKeyBytes, count: privKeyLength)
}
public func encode(with coder: NSCoder) { fatalError("Shouldn't be encoding this type") }
}
}

@ -2,120 +2,22 @@
import Foundation
import GRDB
import YapDatabase
enum _003_YDBToGRDBMigration: Migration {
static let target: TargetMigrations.Identifier = .utilitiesKit
static let identifier: String = "YDBToGRDBMigration" // stringlint:disable
static let needsConfigSync: Bool = false
static let minExpectedRunDuration: TimeInterval = 0.1
static let fetchedTables: [(TableRecord & FetchableRecord).Type] = []
static let fetchedTables: [(TableRecord & FetchableRecord).Type] = [Identity.self]
static let createdOrAlteredTables: [(TableRecord & FetchableRecord).Type] = []
static func migrate(_ db: Database) throws {
guard let dbConnection: YapDatabaseConnection = SUKLegacy.newDatabaseConnection() else {
SNLogNotTests("[Migration Warning] No legacy database, skipping \(target.key(with: self))")
return
}
// MARK: - Read from Legacy Database
// Note: Want to exclude the Snode's we already added from the 'onionRequestPathResult'
var registeredNumber: String?
var seedHexString: String?
var userEd25519SecretKeyHexString: String?
var userEd25519PublicKeyHexString: String?
var userX25519KeyPair: SUKLegacy.KeyPair?
// Map the Legacy types for the NSKeyedUnarchiver
NSKeyedUnarchiver.setClass(
SUKLegacy.KeyPair.self,
forClassName: "ECKeyPair" // stringlint:disable
)
dbConnection.read { transaction in
// MARK: --Identity keys
registeredNumber = transaction.object(
forKey: SUKLegacy.userAccountRegisteredNumberKey,
inCollection: SUKLegacy.userAccountCollection
) as? String
// Note: The 'seed', 'ed25519SecretKey' and 'ed25519PublicKey' were
// all previously stored as hex strings, so we need to convert them
// to data before we store them in the new database
seedHexString = transaction.object(
forKey: SUKLegacy.identityKeyStoreSeedKey,
inCollection: SUKLegacy.identityKeyStoreCollection
) as? String
userEd25519SecretKeyHexString = transaction.object(
forKey: SUKLegacy.identityKeyStoreEd25519SecretKey,
inCollection: SUKLegacy.identityKeyStoreCollection
) as? String
userEd25519PublicKeyHexString = transaction.object(
forKey: SUKLegacy.identityKeyStoreEd25519PublicKey,
inCollection: SUKLegacy.identityKeyStoreCollection
) as? String
userX25519KeyPair = transaction.object(
forKey: SUKLegacy.identityKeyStoreIdentityKey,
inCollection: SUKLegacy.identityKeyStoreCollection
) as? SUKLegacy.KeyPair
}
// No need to continue if the user isn't registered
if registeredNumber == nil { return }
// If the user is registered then it's all-or-nothing for these values
guard
let seedHexString: String = seedHexString,
let userEd25519SecretKeyHexString: String = userEd25519SecretKeyHexString,
let userEd25519PublicKeyHexString: String = userEd25519PublicKeyHexString,
let userX25519KeyPair: SUKLegacy.KeyPair = userX25519KeyPair
else {
// If this is a fresh install then we would have created all of the Identity
// values directly within the 'Identity' table so this is actually a valid
// case and we don't need to throw
if try Identity.fetchCount(db) == Identity.Variant.allCases.count {
return
}
throw StorageError.migrationFailed
}
// MARK: - Insert into GRDB
try autoreleasepool {
// MARK: --Identity keys
try Identity(
variant: .seed,
data: Data(hex: seedHexString)
).migrationSafeInsert(db)
try Identity(
variant: .ed25519SecretKey,
data: Data(hex: userEd25519SecretKeyHexString)
).migrationSafeInsert(db)
try Identity(
variant: .ed25519PublicKey,
data: Data(hex: userEd25519PublicKeyHexString)
).migrationSafeInsert(db)
try Identity(
variant: .x25519PrivateKey,
data: userX25519KeyPair.privateKey
).migrationSafeInsert(db)
try Identity(
variant: .x25519PublicKey,
data: userX25519KeyPair.publicKey
).migrationSafeInsert(db)
}
!SNUtilitiesKit.isRunningTests &&
Identity.userExists(db)
else { return Storage.update(progress: 1, for: self, in: target) }
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
SNLogNotTests("[Migration Error] Attempted to perform legacy migation")
throw StorageError.migrationNoLongerSupported
}
}

@ -2,7 +2,6 @@
import Foundation
import GRDB
import YapDatabase
enum _004_AddJobPriority: Migration {
static let target: TargetMigrations.Identifier = .utilitiesKit

@ -249,7 +249,6 @@ open class Storage {
self?.migrationsCompleted.mutate { $0 = true }
self?.migrationProgressUpdater = nil
self?.migrationRequirementProcesser = nil
SUKLegacy.clearLegacyDatabaseInstance()
// Process any remaining migration requirements
if !remainingMigrationRequirements.isEmpty {
@ -421,10 +420,6 @@ open class Storage {
}
public static func resetAllStorage() {
// Just in case they haven't been removed for some reason, delete the legacy database & keys
SUKLegacy.clearLegacyDatabaseInstance()
try? SUKLegacy.deleteLegacyDatabaseFilesAndKey()
Storage.shared.isValid = false
Storage.internalHasCreatedValidInstance.mutate { $0 = false }
Storage.shared.migrationsCompleted.mutate { $0 = false }

@ -7,6 +7,7 @@ public enum StorageError: Error {
case databaseInvalid
case startupFailed
case migrationFailed
case migrationNoLongerSupported
case invalidKeySpec
case keySpecCreationFailed
case keySpecInaccessible

Loading…
Cancel
Save