Added more unit tests

Removed an unused endpoint
Moved 'Dependencies' into the Utilities folder (also out from being nested within 'OpenGroupAPI' since it can be broader than that)
Finished adding unit tests for the OpenGroupAPI
pull/592/head
Morgan Pretty 3 years ago
parent b6a6f77d4e
commit 65f14cf0a1

@ -805,6 +805,17 @@
FD859F0027C4691300510D0C /* MockDataGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD859EFF27C4691300510D0C /* MockDataGenerator.swift */; }; FD859F0027C4691300510D0C /* MockDataGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD859EFF27C4691300510D0C /* MockDataGenerator.swift */; };
FD88BAD927A7439C00BBC442 /* MessageRequestsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD88BAD827A7439C00BBC442 /* MessageRequestsCell.swift */; }; FD88BAD927A7439C00BBC442 /* MessageRequestsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD88BAD827A7439C00BBC442 /* MessageRequestsCell.swift */; };
FD88BADB27A750F200BBC442 /* MessageRequestsMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */; }; FD88BADB27A750F200BBC442 /* MessageRequestsMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */; };
FDC2908727D7047F005DAE71 /* RoomSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2908627D7047F005DAE71 /* RoomSpec.swift */; };
FDC2908927D70656005DAE71 /* RoomPollInfoSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2908827D70656005DAE71 /* RoomPollInfoSpec.swift */; };
FDC2908B27D707F3005DAE71 /* SendMessageRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2908A27D707F3005DAE71 /* SendMessageRequestSpec.swift */; };
FDC2908D27D70905005DAE71 /* UpdateMessageRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2908C27D70905005DAE71 /* UpdateMessageRequestSpec.swift */; };
FDC2908F27D70938005DAE71 /* SendDirectMessageRequestSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2908E27D70938005DAE71 /* SendDirectMessageRequestSpec.swift */; };
FDC2909127D709CA005DAE71 /* SOGSMessageSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909027D709CA005DAE71 /* SOGSMessageSpec.swift */; };
FDC2909427D710B4005DAE71 /* SOGSEndpointSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909327D710B4005DAE71 /* SOGSEndpointSpec.swift */; };
FDC2909627D71252005DAE71 /* SOGSErrorSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909527D71252005DAE71 /* SOGSErrorSpec.swift */; };
FDC2909827D7129B005DAE71 /* PersonalizationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909727D7129B005DAE71 /* PersonalizationSpec.swift */; };
FDC2909A27D71376005DAE71 /* NonceGeneratorSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909927D71376005DAE71 /* NonceGeneratorSpec.swift */; };
FDC2909C27D713D2005DAE71 /* SodiumProtocolsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC2909B27D713D2005DAE71 /* SodiumProtocolsSpec.swift */; };
FDC4380927B31D4E00C60D73 /* SOGSError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC4380827B31D4E00C60D73 /* SOGSError.swift */; }; FDC4380927B31D4E00C60D73 /* SOGSError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC4380827B31D4E00C60D73 /* SOGSError.swift */; };
FDC4381527B329CE00C60D73 /* NonceGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC4381427B329CE00C60D73 /* NonceGenerator.swift */; }; FDC4381527B329CE00C60D73 /* NonceGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC4381427B329CE00C60D73 /* NonceGenerator.swift */; };
FDC4381727B32EC700C60D73 /* Personalization.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC4381627B32EC700C60D73 /* Personalization.swift */; }; FDC4381727B32EC700C60D73 /* Personalization.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDC4381627B32EC700C60D73 /* Personalization.swift */; };
@ -1940,6 +1951,17 @@
FD88BAD827A7439C00BBC442 /* MessageRequestsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsCell.swift; sourceTree = "<group>"; }; FD88BAD827A7439C00BBC442 /* MessageRequestsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsCell.swift; sourceTree = "<group>"; };
FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsMigration.swift; sourceTree = "<group>"; }; FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsMigration.swift; sourceTree = "<group>"; };
FD9039443F7CB729CF71350E /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; sourceTree = "<group>"; }; FD9039443F7CB729CF71350E /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; sourceTree = "<group>"; };
FDC2908627D7047F005DAE71 /* RoomSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSpec.swift; sourceTree = "<group>"; };
FDC2908827D70656005DAE71 /* RoomPollInfoSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomPollInfoSpec.swift; sourceTree = "<group>"; };
FDC2908A27D707F3005DAE71 /* SendMessageRequestSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendMessageRequestSpec.swift; sourceTree = "<group>"; };
FDC2908C27D70905005DAE71 /* UpdateMessageRequestSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateMessageRequestSpec.swift; sourceTree = "<group>"; };
FDC2908E27D70938005DAE71 /* SendDirectMessageRequestSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendDirectMessageRequestSpec.swift; sourceTree = "<group>"; };
FDC2909027D709CA005DAE71 /* SOGSMessageSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOGSMessageSpec.swift; sourceTree = "<group>"; };
FDC2909327D710B4005DAE71 /* SOGSEndpointSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOGSEndpointSpec.swift; sourceTree = "<group>"; };
FDC2909527D71252005DAE71 /* SOGSErrorSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOGSErrorSpec.swift; sourceTree = "<group>"; };
FDC2909727D7129B005DAE71 /* PersonalizationSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonalizationSpec.swift; sourceTree = "<group>"; };
FDC2909927D71376005DAE71 /* NonceGeneratorSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonceGeneratorSpec.swift; sourceTree = "<group>"; };
FDC2909B27D713D2005DAE71 /* SodiumProtocolsSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SodiumProtocolsSpec.swift; sourceTree = "<group>"; };
FDC4380827B31D4E00C60D73 /* SOGSError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOGSError.swift; sourceTree = "<group>"; }; FDC4380827B31D4E00C60D73 /* SOGSError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SOGSError.swift; sourceTree = "<group>"; };
FDC4381427B329CE00C60D73 /* NonceGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonceGenerator.swift; sourceTree = "<group>"; }; FDC4381427B329CE00C60D73 /* NonceGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonceGenerator.swift; sourceTree = "<group>"; };
FDC4381627B32EC700C60D73 /* Personalization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Personalization.swift; sourceTree = "<group>"; }; FDC4381627B32EC700C60D73 /* Personalization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Personalization.swift; sourceTree = "<group>"; };
@ -3397,6 +3419,7 @@
FDC4383D27B4708600C60D73 /* Atomic.swift */, FDC4383D27B4708600C60D73 /* Atomic.swift */,
FD83B9A927CF149D005E1583 /* ContactUtilities.swift */, FD83B9A927CF149D005E1583 /* ContactUtilities.swift */,
FD859EF127BF6BA200510D0C /* Data+Utilities.swift */, FD859EF127BF6BA200510D0C /* Data+Utilities.swift */,
FDC438C027BB4E6800C60D73 /* Dependencies.swift */,
C38EF309255B6DBE007E1867 /* DeviceSleepManager.swift */, C38EF309255B6DBE007E1867 /* DeviceSleepManager.swift */,
C37F53E8255BA9BB002AEA92 /* Environment.h */, C37F53E8255BA9BB002AEA92 /* Environment.h */,
C37F5402255BA9ED002AEA92 /* Environment.m */, C37F5402255BA9ED002AEA92 /* Environment.m */,
@ -3865,6 +3888,12 @@
FD83B9C227CF33F7005E1583 /* ServerSpec.swift */, FD83B9C227CF33F7005E1583 /* ServerSpec.swift */,
FD83B9C427CF3E2A005E1583 /* OpenGroupSpec.swift */, FD83B9C427CF3E2A005E1583 /* OpenGroupSpec.swift */,
FD83B9C627CF3F10005E1583 /* CapabilitiesSpec.swift */, FD83B9C627CF3F10005E1583 /* CapabilitiesSpec.swift */,
FDC2908627D7047F005DAE71 /* RoomSpec.swift */,
FDC2908827D70656005DAE71 /* RoomPollInfoSpec.swift */,
FDC2908A27D707F3005DAE71 /* SendMessageRequestSpec.swift */,
FDC2908C27D70905005DAE71 /* UpdateMessageRequestSpec.swift */,
FDC2909027D709CA005DAE71 /* SOGSMessageSpec.swift */,
FDC2908E27D70938005DAE71 /* SendDirectMessageRequestSpec.swift */,
); );
path = Models; path = Models;
sourceTree = "<group>"; sourceTree = "<group>";
@ -3885,6 +3914,18 @@
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
FDC2909227D710A9005DAE71 /* Types */ = {
isa = PBXGroup;
children = (
FDC2909327D710B4005DAE71 /* SOGSEndpointSpec.swift */,
FDC2909527D71252005DAE71 /* SOGSErrorSpec.swift */,
FDC2909727D7129B005DAE71 /* PersonalizationSpec.swift */,
FDC2909927D71376005DAE71 /* NonceGeneratorSpec.swift */,
FDC2909B27D713D2005DAE71 /* SodiumProtocolsSpec.swift */,
);
path = Types;
sourceTree = "<group>";
};
FDC4380727B31D3A00C60D73 /* Types */ = { FDC4380727B31D3A00C60D73 /* Types */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -3892,7 +3933,6 @@
FDC4380827B31D4E00C60D73 /* SOGSError.swift */, FDC4380827B31D4E00C60D73 /* SOGSError.swift */,
FDC4381627B32EC700C60D73 /* Personalization.swift */, FDC4381627B32EC700C60D73 /* Personalization.swift */,
FDC4381427B329CE00C60D73 /* NonceGenerator.swift */, FDC4381427B329CE00C60D73 /* NonceGenerator.swift */,
FDC438C027BB4E6800C60D73 /* Dependencies.swift */,
FDC438C227BB512200C60D73 /* SodiumProtocols.swift */, FDC438C227BB512200C60D73 /* SodiumProtocols.swift */,
); );
path = Types; path = Types;
@ -3972,6 +4012,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FD83B9C127CF33EE005E1583 /* Models */, FD83B9C127CF33EE005E1583 /* Models */,
FDC2909227D710A9005DAE71 /* Types */,
FDC4389927BA002500C60D73 /* OpenGroupAPISpec.swift */, FDC4389927BA002500C60D73 /* OpenGroupAPISpec.swift */,
); );
path = "Open Groups"; path = "Open Groups";
@ -5578,16 +5619,27 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
FD859EFA27C2F5C500510D0C /* TestGenericHash.swift in Sources */, FD859EFA27C2F5C500510D0C /* TestGenericHash.swift in Sources */,
FDC2909427D710B4005DAE71 /* SOGSEndpointSpec.swift in Sources */,
FDC2909127D709CA005DAE71 /* SOGSMessageSpec.swift in Sources */,
FDC2909627D71252005DAE71 /* SOGSErrorSpec.swift in Sources */,
FDC2908727D7047F005DAE71 /* RoomSpec.swift in Sources */,
FDC2909C27D713D2005DAE71 /* SodiumProtocolsSpec.swift in Sources */,
FD83B9C327CF33F7005E1583 /* ServerSpec.swift in Sources */, FD83B9C327CF33F7005E1583 /* ServerSpec.swift in Sources */,
FD83B9C727CF3F10005E1583 /* CapabilitiesSpec.swift in Sources */, FD83B9C727CF3F10005E1583 /* CapabilitiesSpec.swift in Sources */,
FDC2909A27D71376005DAE71 /* NonceGeneratorSpec.swift in Sources */,
FD859EF827C2F58900510D0C /* TestAeadXChaCha20Poly1305Ietf.swift in Sources */, FD859EF827C2F58900510D0C /* TestAeadXChaCha20Poly1305Ietf.swift in Sources */,
FDC2909827D7129B005DAE71 /* PersonalizationSpec.swift in Sources */,
FD859EF427C2F49200510D0C /* TestSodium.swift in Sources */, FD859EF427C2F49200510D0C /* TestSodium.swift in Sources */,
FD859EFC27C2F60700510D0C /* TestEd25519.swift in Sources */, FD859EFC27C2F60700510D0C /* TestEd25519.swift in Sources */,
FD83B9C027CF2294005E1583 /* TestConstants.swift in Sources */, FD83B9C027CF2294005E1583 /* TestConstants.swift in Sources */,
FDC4389A27BA002500C60D73 /* OpenGroupAPISpec.swift in Sources */, FDC4389A27BA002500C60D73 /* OpenGroupAPISpec.swift in Sources */,
FD83B9C527CF3E2A005E1583 /* OpenGroupSpec.swift in Sources */, FD83B9C527CF3E2A005E1583 /* OpenGroupSpec.swift in Sources */,
FDC2908B27D707F3005DAE71 /* SendMessageRequestSpec.swift in Sources */,
FDC2908F27D70938005DAE71 /* SendDirectMessageRequestSpec.swift in Sources */,
FDC438BD27BB2AB400C60D73 /* Mockable.swift in Sources */, FDC438BD27BB2AB400C60D73 /* Mockable.swift in Sources */,
FD859EF627C2F52C00510D0C /* TestSign.swift in Sources */, FD859EF627C2F52C00510D0C /* TestSign.swift in Sources */,
FDC2908927D70656005DAE71 /* RoomPollInfoSpec.swift in Sources */,
FDC2908D27D70905005DAE71 /* UpdateMessageRequestSpec.swift in Sources */,
FDC4389D27BA01F000C60D73 /* TestStorage.swift in Sources */, FDC4389D27BA01F000C60D73 /* TestStorage.swift in Sources */,
FD83B9D227D59495005E1583 /* TestUserDefaults.swift in Sources */, FD83B9D227D59495005E1583 /* TestUserDefaults.swift in Sources */,
); );

@ -813,7 +813,8 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak self] _ in alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak self] _ in
let publicKey = message.authorId let publicKey = message.authorId
guard let openGroup = Storage.shared.getOpenGroup(for: threadID) else { return } guard let openGroup = Storage.shared.getOpenGroup(for: threadID) else { return }
let promise = OpenGroupAPI.userBanAndDeleteAllMessage(publicKey, for: [openGroup.room], on: openGroup.server)
let promise = OpenGroupAPI.userBanAndDeleteAllMessage(publicKey, from: [openGroup.room], on: openGroup.server)
promise.catch(on: DispatchQueue.main) { _ in promise.catch(on: DispatchQueue.main) { _ in
OWSAlerts.showErrorAlert(message: NSLocalizedString("context_menu_ban_user_error_alert_message", comment: "")) OWSAlerts.showErrorAlert(message: NSLocalizedString("context_menu_ban_user_error_alert_message", comment: ""))
} }

@ -143,13 +143,13 @@ protocol BatchRequestInfoType {
// MARK: - Convenience // MARK: - Convenience
public extension Decodable { public extension Decodable {
static func decoded(from data: Data, using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) throws -> Self { static func decoded(from data: Data, using dependencies: Dependencies = Dependencies()) throws -> Self {
return try data.decoded(as: Self.self, using: dependencies) return try data.decoded(as: Self.self, using: dependencies)
} }
} }
extension Promise where T == (OnionRequestResponseInfoType, Data?) { extension Promise where T == (OnionRequestResponseInfoType, Data?) {
func decoded(as types: OpenGroupAPI.BatchResponseTypes, on queue: DispatchQueue? = nil, using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> Promise<OpenGroupAPI.BatchResponse> { func decoded(as types: OpenGroupAPI.BatchResponseTypes, on queue: DispatchQueue? = nil, using dependencies: Dependencies = Dependencies()) -> Promise<OpenGroupAPI.BatchResponse> {
self.map(on: queue) { responseInfo, maybeData -> OpenGroupAPI.BatchResponse in self.map(on: queue) { responseInfo, maybeData -> OpenGroupAPI.BatchResponse in
// Need to split the data into an array of data so each item can be Decoded correctly // Need to split the data into an array of data so each item can be Decoded correctly
guard let data: Data = maybeData else { throw HTTP.Error.parsingFailed } guard let data: Data = maybeData else { throw HTTP.Error.parsingFailed }

@ -108,7 +108,7 @@ extension OpenGroupAPI.RoomPollInfo {
defaultWrite: room.defaultWrite, defaultWrite: room.defaultWrite,
upload: room.upload, upload: room.upload,
defaultUpload: room.defaultUpload, defaultUpload: room.defaultUpload,
details: nil details: room
) )
} }
} }

@ -3,7 +3,7 @@
import Foundation import Foundation
extension OpenGroupAPI { extension OpenGroupAPI {
public struct Message: Codable { public struct Message: Codable, Equatable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case id case id
case sender = "session_id" case sender = "session_id"
@ -47,7 +47,7 @@ extension OpenGroupAPI.Message {
guard let sender: String = maybeSender, let data = Data(base64Encoded: base64EncodedData), let signature = Data(base64Encoded: base64EncodedSignature) else { guard let sender: String = maybeSender, let data = Data(base64Encoded: base64EncodedData), let signature = Data(base64Encoded: base64EncodedSignature) else {
throw HTTP.Error.parsingFailed throw HTTP.Error.parsingFailed
} }
guard let dependencies: OpenGroupAPI.Dependencies = decoder.userInfo[OpenGroupAPI.Dependencies.userInfoKey] as? OpenGroupAPI.Dependencies else { guard let dependencies: Dependencies = decoder.userInfo[Dependencies.userInfoKey] as? Dependencies else {
throw HTTP.Error.parsingFailed throw HTTP.Error.parsingFailed
} }

@ -3,7 +3,7 @@
import Foundation import Foundation
extension OpenGroupAPI { extension OpenGroupAPI {
public struct SendDirectMessageResponse: Codable { public struct SendDirectMessageResponse: Codable, Equatable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case id case id
case sender case sender

@ -3,7 +3,7 @@
import Foundation import Foundation
extension OpenGroupAPI { extension OpenGroupAPI {
public struct UserDeleteMessagesResponse: Codable { public struct UserDeleteMessagesResponse: Codable, Equatable {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case id case id
case messagesDeleted = "messages_deleted" case messagesDeleted = "messages_deleted"

@ -812,7 +812,7 @@ public enum OpenGroupAPI {
/// - dependencies: Injected dependencies (used for unit testing) /// - dependencies: Injected dependencies (used for unit testing)
public static func userDeleteMessages( public static func userDeleteMessages(
_ sessionId: String, _ sessionId: String,
for roomTokens: [String]?, from roomTokens: [String]?,
on server: String, on server: String,
using dependencies: Dependencies = Dependencies() using dependencies: Dependencies = Dependencies()
) -> Promise<(OnionRequestResponseInfoType, UserDeleteMessagesResponse)> { ) -> Promise<(OnionRequestResponseInfoType, UserDeleteMessagesResponse)> {
@ -837,7 +837,7 @@ public enum OpenGroupAPI {
/// methods for the documented behaviour of each method /// methods for the documented behaviour of each method
public static func userBanAndDeleteAllMessage( public static func userBanAndDeleteAllMessage(
_ sessionId: String, _ sessionId: String,
for roomTokens: [String]?, from roomTokens: [String]?,
on server: String, on server: String,
using dependencies: Dependencies = Dependencies() using dependencies: Dependencies = Dependencies()
) -> Promise<[OnionRequestResponseInfoType]> { ) -> Promise<[OnionRequestResponseInfoType]> {

@ -18,7 +18,7 @@ public final class OpenGroupManager: NSObject {
public var timeSinceLastPoll: [String: TimeInterval] = [:] public var timeSinceLastPoll: [String: TimeInterval] = [:]
fileprivate var _timeSinceLastOpen: TimeInterval? fileprivate var _timeSinceLastOpen: TimeInterval?
public func getTimeSinceLastOpen(using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> TimeInterval { public func getTimeSinceLastOpen(using dependencies: Dependencies = Dependencies()) -> TimeInterval {
if let storedTimeSinceLastOpen: TimeInterval = _timeSinceLastOpen { if let storedTimeSinceLastOpen: TimeInterval = _timeSinceLastOpen {
return storedTimeSinceLastOpen return storedTimeSinceLastOpen
} }
@ -67,7 +67,7 @@ public final class OpenGroupManager: NSObject {
// MARK: - Adding & Removing // MARK: - Adding & Removing
public func add(roomToken: String, server: String, publicKey: String, isConfigMessage: Bool, using transaction: YapDatabaseReadWriteTransaction, dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> Promise<Void> { public func add(roomToken: String, server: String, publicKey: String, isConfigMessage: Bool, using transaction: YapDatabaseReadWriteTransaction, dependencies: Dependencies = Dependencies()) -> Promise<Void> {
// If we are currently polling for this server and already have a TSGroupThread for this room the do nothing // If we are currently polling for this server and already have a TSGroupThread for this room the do nothing
let groupId: Data = LKGroupUtilities.getEncodedOpenGroupIDAsData("\(server).\(roomToken)") let groupId: Data = LKGroupUtilities.getEncodedOpenGroupIDAsData("\(server).\(roomToken)")
@ -163,7 +163,7 @@ public final class OpenGroupManager: NSObject {
_ capabilities: OpenGroupAPI.Capabilities, _ capabilities: OpenGroupAPI.Capabilities,
on server: String, on server: String,
using transaction: YapDatabaseReadWriteTransaction, using transaction: YapDatabaseReadWriteTransaction,
dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies() dependencies: Dependencies = Dependencies()
) { ) {
let updatedServer: OpenGroupAPI.Server = OpenGroupAPI.Server( let updatedServer: OpenGroupAPI.Server = OpenGroupAPI.Server(
name: server, name: server,
@ -179,7 +179,7 @@ public final class OpenGroupManager: NSObject {
for roomToken: String, for roomToken: String,
on server: String, on server: String,
using transaction: YapDatabaseReadWriteTransaction, using transaction: YapDatabaseReadWriteTransaction,
dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies(), dependencies: Dependencies = Dependencies(),
completion: (() -> ())? = nil completion: (() -> ())? = nil
) { ) {
OpenGroupManager.handlePollInfo( OpenGroupManager.handlePollInfo(
@ -199,7 +199,7 @@ public final class OpenGroupManager: NSObject {
for roomToken: String, for roomToken: String,
on server: String, on server: String,
using transaction: YapDatabaseReadWriteTransaction, using transaction: YapDatabaseReadWriteTransaction,
dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies(), dependencies: Dependencies = Dependencies(),
completion: (() -> ())? = nil completion: (() -> ())? = nil
) { ) {
// Create the open group model and get or create the thread // Create the open group model and get or create the thread
@ -307,7 +307,7 @@ public final class OpenGroupManager: NSObject {
on server: String, on server: String,
isBackgroundPoll: Bool, isBackgroundPoll: Bool,
using transaction: YapDatabaseReadWriteTransaction, using transaction: YapDatabaseReadWriteTransaction,
dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies() dependencies: Dependencies = Dependencies()
) { ) {
// Sorting the messages by server ID before importing them fixes an issue where messages // Sorting the messages by server ID before importing them fixes an issue where messages
// that quote older messages can't find those older messages // that quote older messages can't find those older messages
@ -371,7 +371,7 @@ public final class OpenGroupManager: NSObject {
on server: String, on server: String,
isBackgroundPoll: Bool, isBackgroundPoll: Bool,
using transaction: YapDatabaseReadWriteTransaction, using transaction: YapDatabaseReadWriteTransaction,
dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies() dependencies: Dependencies = Dependencies()
) { ) {
// Don't need to do anything if we have no messages (it's a valid case) // Don't need to do anything if we have no messages (it's a valid case)
guard !messages.isEmpty else { return } guard !messages.isEmpty else { return }
@ -476,10 +476,10 @@ public final class OpenGroupManager: NSObject {
/// This method specifies if the given publicKey is a moderator or an admin within a specified Open Group /// This method specifies if the given publicKey is a moderator or an admin within a specified Open Group
@objc(isUserModeratorOrAdmin:forRoom:onServer:) @objc(isUserModeratorOrAdmin:forRoom:onServer:)
public static func isUserModeratorOrAdmin(_ publicKey: String, for room: String, on server: String) -> Bool { public static func isUserModeratorOrAdmin(_ publicKey: String, for room: String, on server: String) -> Bool {
return isUserModeratorOrAdmin(publicKey, for: room, on: server, using: OpenGroupAPI.Dependencies()) return isUserModeratorOrAdmin(publicKey, for: room, on: server)
} }
public static func isUserModeratorOrAdmin(_ publicKey: String, for room: String, on server: String, using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> Bool { public static func isUserModeratorOrAdmin(_ publicKey: String, for room: String, on server: String, using dependencies: Dependencies = Dependencies()) -> Bool {
let modAndAdminKeys: Set<String> = (OpenGroupManager.shared.cache.moderators[server]?[room] ?? Set()) let modAndAdminKeys: Set<String> = (OpenGroupManager.shared.cache.moderators[server]?[room] ?? Set())
.union(OpenGroupManager.shared.cache.admins[server]?[room] ?? Set()) .union(OpenGroupManager.shared.cache.admins[server]?[room] ?? Set())
@ -527,7 +527,7 @@ public final class OpenGroupManager: NSObject {
} }
} }
public static func getDefaultRoomsIfNeeded(using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) { public static func getDefaultRoomsIfNeeded(using dependencies: Dependencies = Dependencies()) {
// Note: If we already have a 'defaultRoomsPromise' then there is no need to get it again // Note: If we already have a 'defaultRoomsPromise' then there is no need to get it again
guard OpenGroupManager.shared.cache.defaultRoomsPromise == nil else { return } guard OpenGroupManager.shared.cache.defaultRoomsPromise == nil else { return }
@ -572,7 +572,7 @@ public final class OpenGroupManager: NSObject {
_ fileId: UInt64, _ fileId: UInt64,
for roomToken: String, for roomToken: String,
on server: String, on server: String,
using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies() using dependencies: Dependencies = Dependencies()
) -> Promise<Data> { ) -> Promise<Data> {
// Normally the image for a given group is stored with the group thread, so it's only // Normally the image for a given group is stored with the group thread, so it's only
// fetched once. However, on the join open group screen we show images for groups the // fetched once. However, on the join open group screen we show images for groups the

@ -1,148 +0,0 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Sodium
import SessionSnodeKit
import SessionUtilitiesKit
// MARK: - Dependencies
extension OpenGroupAPI {
public class Dependencies {
private var _api: OnionRequestAPIType.Type?
public var api: OnionRequestAPIType.Type {
get { getValueSettingIfNull(&_api) { OnionRequestAPI.self } }
set { _api = newValue }
}
private var _storage: SessionMessagingKitStorageProtocol?
public var storage: SessionMessagingKitStorageProtocol {
get { getValueSettingIfNull(&_storage) { SNMessagingKitConfiguration.shared.storage } }
set { _storage = newValue }
}
private var _sodium: SodiumType?
public var sodium: SodiumType {
get { getValueSettingIfNull(&_sodium) { Sodium() } }
set { _sodium = newValue }
}
private var _aeadXChaCha20Poly1305Ietf: AeadXChaCha20Poly1305IetfType?
public var aeadXChaCha20Poly1305Ietf: AeadXChaCha20Poly1305IetfType {
get { getValueSettingIfNull(&_aeadXChaCha20Poly1305Ietf) { sodium.getAeadXChaCha20Poly1305Ietf() } }
set { _aeadXChaCha20Poly1305Ietf = newValue }
}
private var _sign: SignType?
public var sign: SignType {
get { getValueSettingIfNull(&_sign) { sodium.getSign() } }
set { _sign = newValue }
}
private var _genericHash: GenericHashType?
public var genericHash: GenericHashType {
get { getValueSettingIfNull(&_genericHash) { sodium.getGenericHash() } }
set { _genericHash = newValue }
}
private var _ed25519: Ed25519Type.Type?
public var ed25519: Ed25519Type.Type {
get { getValueSettingIfNull(&_ed25519) { Ed25519.self } }
set { _ed25519 = newValue }
}
private var _nonceGenerator16: NonceGenerator16ByteType?
public var nonceGenerator16: NonceGenerator16ByteType {
get { getValueSettingIfNull(&_nonceGenerator16) { NonceGenerator16Byte() } }
set { _nonceGenerator16 = newValue }
}
private var _nonceGenerator24: NonceGenerator24ByteType?
public var nonceGenerator24: NonceGenerator24ByteType {
get { getValueSettingIfNull(&_nonceGenerator24) { NonceGenerator24Byte() } }
set { _nonceGenerator24 = newValue }
}
private var _standardUserDefaults: UserDefaultsType?
public var standardUserDefaults: UserDefaultsType {
get { getValueSettingIfNull(&_standardUserDefaults) { UserDefaults.standard } }
set { _standardUserDefaults = newValue }
}
private var _date: Date?
public var date: Date {
get { getValueSettingIfNull(&_date) { Date() } }
set { _date = newValue }
}
// MARK: - Initialization
public init(
api: OnionRequestAPIType.Type? = nil,
storage: SessionMessagingKitStorageProtocol? = nil,
sodium: SodiumType? = nil,
aeadXChaCha20Poly1305Ietf: AeadXChaCha20Poly1305IetfType? = nil,
sign: SignType? = nil,
genericHash: GenericHashType? = nil,
ed25519: Ed25519Type.Type? = nil,
nonceGenerator16: NonceGenerator16ByteType? = nil,
nonceGenerator24: NonceGenerator24ByteType? = nil,
standardUserDefaults: UserDefaultsType? = nil,
date: Date? = nil
) {
_api = api
_storage = storage
_sodium = sodium
_aeadXChaCha20Poly1305Ietf = aeadXChaCha20Poly1305Ietf
_sign = sign
_genericHash = genericHash
_ed25519 = ed25519
_nonceGenerator16 = nonceGenerator16
_nonceGenerator24 = nonceGenerator24
_standardUserDefaults = standardUserDefaults
_date = date
}
// MARK: - Convenience
public func with(
api: OnionRequestAPIType.Type? = nil,
storage: SessionMessagingKitStorageProtocol? = nil,
sodium: SodiumType? = nil,
aeadXChaCha20Poly1305Ietf: AeadXChaCha20Poly1305IetfType? = nil,
sign: SignType? = nil,
genericHash: GenericHashType? = nil,
ed25519: Ed25519Type.Type? = nil,
nonceGenerator16: NonceGenerator16ByteType? = nil,
nonceGenerator24: NonceGenerator24ByteType? = nil,
standardUserDefaults: UserDefaultsType? = nil,
date: Date? = nil
) -> Dependencies {
return Dependencies(
api: (api ?? self._api),
storage: (storage ?? self._storage),
sodium: (sodium ?? self._sodium),
aeadXChaCha20Poly1305Ietf: (aeadXChaCha20Poly1305Ietf ?? self._aeadXChaCha20Poly1305Ietf),
sign: (sign ?? self._sign),
genericHash: (genericHash ?? self._genericHash),
ed25519: (ed25519 ?? self._ed25519),
nonceGenerator16: (nonceGenerator16 ?? self._nonceGenerator16),
nonceGenerator24: (nonceGenerator24 ?? self._nonceGenerator24),
standardUserDefaults: (standardUserDefaults ?? self._standardUserDefaults),
date: (date ?? self._date)
)
}
}
}
// MARK: - Convenience
fileprivate func getValueSettingIfNull<T>(_ maybeValue: inout T?, _ valueGenerator: () -> T) -> T {
guard let value: T = maybeValue else {
let value: T = valueGenerator()
maybeValue = value
return value
}
return value
}

@ -17,13 +17,9 @@ public protocol NonceGenerator24ByteType {
extension OpenGroupAPI { extension OpenGroupAPI {
public class NonceGenerator16Byte: NonceGenerator, NonceGenerator16ByteType { public class NonceGenerator16Byte: NonceGenerator, NonceGenerator16ByteType {
public var NonceBytes: Int { 16 } public var NonceBytes: Int { 16 }
public init() {}
} }
public class NonceGenerator24Byte: NonceGenerator, NonceGenerator24ByteType { public class NonceGenerator24Byte: NonceGenerator, NonceGenerator24ByteType {
public var NonceBytes: Int { 24 } public var NonceBytes: Int { 24 }
public init() {}
} }
} }

@ -49,7 +49,6 @@ extension OpenGroupAPI {
case userBan(String) case userBan(String)
case userUnban(String) case userUnban(String)
case userPermission(String)
case userModerator(String) case userModerator(String)
case userDeleteMessages(String) case userDeleteMessages(String)
@ -114,7 +113,6 @@ extension OpenGroupAPI {
case .userBan(let sessionId): return "user/\(sessionId)/ban" case .userBan(let sessionId): return "user/\(sessionId)/ban"
case .userUnban(let sessionId): return "user/\(sessionId)/unban" case .userUnban(let sessionId): return "user/\(sessionId)/unban"
case .userPermission(let sessionId): return "user/\(sessionId)/permission"
case .userModerator(let sessionId): return "user/\(sessionId)/moderator" case .userModerator(let sessionId): return "user/\(sessionId)/moderator"
case .userDeleteMessages(let sessionId): return "user/\(sessionId)/deleteMessages" case .userDeleteMessages(let sessionId): return "user/\(sessionId)/deleteMessages"
} }

@ -27,7 +27,7 @@ extension MessageReceiver {
return (Data(plaintext), SessionId(.standard, publicKey: senderX25519PublicKey).hexString) return (Data(plaintext), SessionId(.standard, publicKey: senderX25519PublicKey).hexString)
} }
internal static func decryptWithSessionBlindingProtocol(data: Data, isOutgoing: Bool, otherBlindedPublicKey: String, with openGroupPublicKey: String, userEd25519KeyPair: Box.KeyPair, using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) throws -> (plaintext: Data, senderX25519PublicKey: String) { internal static func decryptWithSessionBlindingProtocol(data: Data, isOutgoing: Bool, otherBlindedPublicKey: String, with openGroupPublicKey: String, userEd25519KeyPair: Box.KeyPair, using dependencies: Dependencies = Dependencies()) throws -> (plaintext: Data, senderX25519PublicKey: String) {
guard let blindedKeyPair = dependencies.sodium.blindedKeyPair(serverPublicKey: openGroupPublicKey, edKeyPair: userEd25519KeyPair, genericHash: dependencies.genericHash) else { guard let blindedKeyPair = dependencies.sodium.blindedKeyPair(serverPublicKey: openGroupPublicKey, edKeyPair: userEd25519KeyPair, genericHash: dependencies.genericHash) else {
throw Error.decryptionFailed throw Error.decryptionFailed
} }

@ -24,7 +24,7 @@ extension MessageSender {
return Data(ciphertext) return Data(ciphertext)
} }
internal static func encryptWithSessionBlindingProtocol(_ plaintext: Data, for recipientBlindedId: String, openGroupPublicKey: String, using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) throws -> Data { internal static func encryptWithSessionBlindingProtocol(_ plaintext: Data, for recipientBlindedId: String, openGroupPublicKey: String, using dependencies: Dependencies = Dependencies()) throws -> Data {
guard SessionId.Prefix(from: recipientBlindedId) == .blinded else { throw Error.signingFailed } guard SessionId.Prefix(from: recipientBlindedId) == .blinded else { throw Error.signingFailed }
guard let userEd25519KeyPair = SNMessagingKitConfiguration.shared.storage.getUserED25519KeyPair() else { guard let userEd25519KeyPair = SNMessagingKitConfiguration.shared.storage.getUserED25519KeyPair() else {
throw Error.noUserED25519KeyPair throw Error.noUserED25519KeyPair

@ -281,7 +281,7 @@ public final class MessageSender : NSObject {
// MARK: - Open Groups // MARK: - Open Groups
internal static func sendToOpenGroupDestination(_ destination: Message.Destination, message: Message, using transaction: Any, dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> Promise<Void> { internal static func sendToOpenGroupDestination(_ destination: Message.Destination, message: Message, using transaction: Any, dependencies: Dependencies = Dependencies()) -> Promise<Void> {
let (promise, seal) = Promise<Void>.pending() let (promise, seal) = Promise<Void>.pending()
let transaction = transaction as! YapDatabaseReadWriteTransaction let transaction = transaction as! YapDatabaseReadWriteTransaction
@ -410,7 +410,7 @@ public final class MessageSender : NSObject {
return promise return promise
} }
internal static func sendToOpenGroupInboxDestination(_ destination: Message.Destination, message: Message, using transaction: Any, dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> Promise<Void> { internal static func sendToOpenGroupInboxDestination(_ destination: Message.Destination, message: Message, using transaction: Any, dependencies: Dependencies = Dependencies()) -> Promise<Void> {
let (promise, seal) = Promise<Void>.pending() let (promise, seal) = Promise<Void>.pending()
let storage = SNMessagingKitConfiguration.shared.storage let storage = SNMessagingKitConfiguration.shared.storage
let transaction = transaction as! YapDatabaseReadWriteTransaction let transaction = transaction as! YapDatabaseReadWriteTransaction

@ -49,7 +49,7 @@ public enum ContactUtilities {
} }
} }
public static func mapping(for blindedId: String, serverPublicKey: String, using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> BlindedIdMapping? { public static func mapping(for blindedId: String, serverPublicKey: String, using dependencies: Dependencies = Dependencies()) -> BlindedIdMapping? {
var result: BlindedIdMapping? var result: BlindedIdMapping?
Storage.write { transaction in Storage.write { transaction in
@ -59,7 +59,7 @@ public enum ContactUtilities {
return result return result
} }
public static func mapping(for blindedId: String, serverPublicKey: String, using transaction: YapDatabaseReadWriteTransaction, dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> BlindedIdMapping? { public static func mapping(for blindedId: String, serverPublicKey: String, using transaction: YapDatabaseReadWriteTransaction, dependencies: Dependencies = Dependencies()) -> BlindedIdMapping? {
// Unfortunately the whole point of id-blinding is to make it hard to reverse-engineer a standard // Unfortunately the whole point of id-blinding is to make it hard to reverse-engineer a standard
// sessionId, as a result in order to see if there is an unblinded contact for this blindedId we // sessionId, as a result in order to see if there is an unblinded contact for this blindedId we
// can only really generate blinded ids for each contact and check if any match // can only really generate blinded ids for each contact and check if any match

@ -4,15 +4,15 @@ import Foundation
// MARK: - Decoding // MARK: - Decoding
extension OpenGroupAPI.Dependencies { extension Dependencies {
static let userInfoKey: CodingUserInfoKey = CodingUserInfoKey(rawValue: "io.oxen.dependencies.codingOptions")! static let userInfoKey: CodingUserInfoKey = CodingUserInfoKey(rawValue: "io.oxen.dependencies.codingOptions")!
} }
public extension Data { public extension Data {
func decoded<T: Decodable>(as type: T.Type, using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) throws -> T { func decoded<T: Decodable>(as type: T.Type, using dependencies: Dependencies = Dependencies()) throws -> T {
do { do {
let decoder: JSONDecoder = JSONDecoder() let decoder: JSONDecoder = JSONDecoder()
decoder.userInfo = [ OpenGroupAPI.Dependencies.userInfoKey: dependencies ] decoder.userInfo = [ Dependencies.userInfoKey: dependencies ]
return try decoder.decode(type, from: self) return try decoder.decode(type, from: self)
} }

@ -0,0 +1,146 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Sodium
import SessionSnodeKit
import SessionUtilitiesKit
// MARK: - Dependencies
public class Dependencies {
private var _api: OnionRequestAPIType.Type?
public var api: OnionRequestAPIType.Type {
get { getValueSettingIfNull(&_api) { OnionRequestAPI.self } }
set { _api = newValue }
}
private var _storage: SessionMessagingKitStorageProtocol?
public var storage: SessionMessagingKitStorageProtocol {
get { getValueSettingIfNull(&_storage) { SNMessagingKitConfiguration.shared.storage } }
set { _storage = newValue }
}
private var _sodium: SodiumType?
public var sodium: SodiumType {
get { getValueSettingIfNull(&_sodium) { Sodium() } }
set { _sodium = newValue }
}
private var _aeadXChaCha20Poly1305Ietf: AeadXChaCha20Poly1305IetfType?
public var aeadXChaCha20Poly1305Ietf: AeadXChaCha20Poly1305IetfType {
get { getValueSettingIfNull(&_aeadXChaCha20Poly1305Ietf) { sodium.getAeadXChaCha20Poly1305Ietf() } }
set { _aeadXChaCha20Poly1305Ietf = newValue }
}
private var _sign: SignType?
public var sign: SignType {
get { getValueSettingIfNull(&_sign) { sodium.getSign() } }
set { _sign = newValue }
}
private var _genericHash: GenericHashType?
public var genericHash: GenericHashType {
get { getValueSettingIfNull(&_genericHash) { sodium.getGenericHash() } }
set { _genericHash = newValue }
}
private var _ed25519: Ed25519Type.Type?
public var ed25519: Ed25519Type.Type {
get { getValueSettingIfNull(&_ed25519) { Ed25519.self } }
set { _ed25519 = newValue }
}
private var _nonceGenerator16: NonceGenerator16ByteType?
public var nonceGenerator16: NonceGenerator16ByteType {
get { getValueSettingIfNull(&_nonceGenerator16) { OpenGroupAPI.NonceGenerator16Byte() } }
set { _nonceGenerator16 = newValue }
}
private var _nonceGenerator24: NonceGenerator24ByteType?
public var nonceGenerator24: NonceGenerator24ByteType {
get { getValueSettingIfNull(&_nonceGenerator24) { OpenGroupAPI.NonceGenerator24Byte() } }
set { _nonceGenerator24 = newValue }
}
private var _standardUserDefaults: UserDefaultsType?
public var standardUserDefaults: UserDefaultsType {
get { getValueSettingIfNull(&_standardUserDefaults) { UserDefaults.standard } }
set { _standardUserDefaults = newValue }
}
private var _date: Date?
public var date: Date {
get { getValueSettingIfNull(&_date) { Date() } }
set { _date = newValue }
}
// MARK: - Initialization
public init(
api: OnionRequestAPIType.Type? = nil,
storage: SessionMessagingKitStorageProtocol? = nil,
sodium: SodiumType? = nil,
aeadXChaCha20Poly1305Ietf: AeadXChaCha20Poly1305IetfType? = nil,
sign: SignType? = nil,
genericHash: GenericHashType? = nil,
ed25519: Ed25519Type.Type? = nil,
nonceGenerator16: NonceGenerator16ByteType? = nil,
nonceGenerator24: NonceGenerator24ByteType? = nil,
standardUserDefaults: UserDefaultsType? = nil,
date: Date? = nil
) {
_api = api
_storage = storage
_sodium = sodium
_aeadXChaCha20Poly1305Ietf = aeadXChaCha20Poly1305Ietf
_sign = sign
_genericHash = genericHash
_ed25519 = ed25519
_nonceGenerator16 = nonceGenerator16
_nonceGenerator24 = nonceGenerator24
_standardUserDefaults = standardUserDefaults
_date = date
}
// MARK: - Convenience
public func with(
api: OnionRequestAPIType.Type? = nil,
storage: SessionMessagingKitStorageProtocol? = nil,
sodium: SodiumType? = nil,
aeadXChaCha20Poly1305Ietf: AeadXChaCha20Poly1305IetfType? = nil,
sign: SignType? = nil,
genericHash: GenericHashType? = nil,
ed25519: Ed25519Type.Type? = nil,
nonceGenerator16: NonceGenerator16ByteType? = nil,
nonceGenerator24: NonceGenerator24ByteType? = nil,
standardUserDefaults: UserDefaultsType? = nil,
date: Date? = nil
) -> Dependencies {
return Dependencies(
api: (api ?? self._api),
storage: (storage ?? self._storage),
sodium: (sodium ?? self._sodium),
aeadXChaCha20Poly1305Ietf: (aeadXChaCha20Poly1305Ietf ?? self._aeadXChaCha20Poly1305Ietf),
sign: (sign ?? self._sign),
genericHash: (genericHash ?? self._genericHash),
ed25519: (ed25519 ?? self._ed25519),
nonceGenerator16: (nonceGenerator16 ?? self._nonceGenerator16),
nonceGenerator24: (nonceGenerator24 ?? self._nonceGenerator24),
standardUserDefaults: (standardUserDefaults ?? self._standardUserDefaults),
date: (date ?? self._date)
)
}
}
// MARK: - Convenience
fileprivate func getValueSettingIfNull<T>(_ maybeValue: inout T?, _ valueGenerator: () -> T) -> T {
guard let value: T = maybeValue else {
let value: T = valueGenerator()
maybeValue = value
return value
}
return value
}

@ -5,7 +5,7 @@ import PromiseKit
import SessionSnodeKit import SessionSnodeKit
extension Promise where T == Data { extension Promise where T == Data {
func decoded<R: Decodable>(as type: R.Type, on queue: DispatchQueue? = nil, using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> Promise<R> { func decoded<R: Decodable>(as type: R.Type, on queue: DispatchQueue? = nil, using dependencies: Dependencies = Dependencies()) -> Promise<R> {
self.map(on: queue) { data -> R in self.map(on: queue) { data -> R in
try data.decoded(as: type, using: dependencies) try data.decoded(as: type, using: dependencies)
} }
@ -13,7 +13,7 @@ extension Promise where T == Data {
} }
extension Promise where T == (OnionRequestResponseInfoType, Data?) { extension Promise where T == (OnionRequestResponseInfoType, Data?) {
func decoded<R: Decodable>(as type: R.Type, on queue: DispatchQueue? = nil, using dependencies: OpenGroupAPI.Dependencies = OpenGroupAPI.Dependencies()) -> Promise<(OnionRequestResponseInfoType, R)> { func decoded<R: Decodable>(as type: R.Type, on queue: DispatchQueue? = nil, using dependencies: Dependencies = Dependencies()) -> Promise<(OnionRequestResponseInfoType, R)> {
self.map(on: queue) { responseInfo, maybeData -> (OnionRequestResponseInfoType, R) in self.map(on: queue) { responseInfo, maybeData -> (OnionRequestResponseInfoType, R) in
guard let data: Data = maybeData else { throw HTTP.Error.parsingFailed } guard let data: Data = maybeData else { throw HTTP.Error.parsingFailed }

@ -0,0 +1,124 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class RoomPollInfoSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a RoomPollInfo") {
context("when initializing with a room") {
it("copies all the relevant values across") {
let room: OpenGroupAPI.Room = OpenGroupAPI.Room(
token: "testToken",
name: "testName",
description: nil,
infoUpdates: 123,
messageSequence: 0,
created: 0,
activeUsers: 234,
activeUsersCutoff: 0,
imageId: nil,
pinnedMessages: nil,
admin: true,
globalAdmin: true,
admins: [],
hiddenAdmins: nil,
moderator: true,
globalModerator: true,
moderators: [],
hiddenModerators: nil,
read: true,
defaultRead: true,
defaultAccessible: true,
write: true,
defaultWrite: true,
upload: true,
defaultUpload: true
)
let roomPollInfo: OpenGroupAPI.RoomPollInfo = OpenGroupAPI.RoomPollInfo(room: room)
expect(roomPollInfo.token).to(equal(room.token))
expect(roomPollInfo.activeUsers).to(equal(room.activeUsers))
expect(roomPollInfo.admin).to(equal(room.admin))
expect(roomPollInfo.globalAdmin).to(equal(room.globalAdmin))
expect(roomPollInfo.moderator).to(equal(room.moderator))
expect(roomPollInfo.globalModerator).to(equal(room.globalModerator))
expect(roomPollInfo.read).to(equal(room.read))
expect(roomPollInfo.defaultRead).to(equal(room.defaultRead))
expect(roomPollInfo.defaultAccessible).to(equal(room.defaultAccessible))
expect(roomPollInfo.write).to(equal(room.write))
expect(roomPollInfo.defaultWrite).to(equal(room.defaultWrite))
expect(roomPollInfo.upload).to(equal(room.upload))
expect(roomPollInfo.defaultUpload).to(equal(room.defaultUpload))
expect(roomPollInfo.details).to(equal(room))
}
}
context("when decoding") {
it("defaults admin and moderator values to false if omitted") {
let roomPollInfoJson: String = """
{
"token": "testToken",
"active_users": 0,
"read": true,
"default_read": true,
"default_accessible": true,
"write": true,
"default_write": true,
"upload": true,
"default_upload": true,
"details": null
}
"""
let roomData: Data = roomPollInfoJson.data(using: .utf8)!
let result: OpenGroupAPI.RoomPollInfo = try! JSONDecoder().decode(OpenGroupAPI.RoomPollInfo.self, from: roomData)
expect(result.admin).to(beFalse())
expect(result.globalAdmin).to(beFalse())
expect(result.moderator).to(beFalse())
expect(result.globalModerator).to(beFalse())
}
it("sets the admin and moderator values when provided") {
let roomPollInfoJson: String = """
{
"token": "testToken",
"active_users": 0,
"admin": true,
"global_admin": true,
"moderator": true,
"global_moderator": true,
"read": true,
"default_read": true,
"default_accessible": true,
"write": true,
"default_write": true,
"upload": true,
"default_upload": true,
"details": null
}
"""
let roomData: Data = roomPollInfoJson.data(using: .utf8)!
let result: OpenGroupAPI.RoomPollInfo = try! JSONDecoder().decode(OpenGroupAPI.RoomPollInfo.self, from: roomData)
expect(result.admin).to(beTrue())
expect(result.globalAdmin).to(beTrue())
expect(result.moderator).to(beTrue())
expect(result.globalModerator).to(beTrue())
}
}
}
}
}

@ -0,0 +1,100 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class RoomSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a Room") {
context("when decoding") {
it("defaults admin and moderator values to false if omitted") {
let roomJson: String = """
{
"token": "testToken",
"name": "testName",
"description": "testDescription",
"info_updates": 0,
"message_sequence": 0,
"created": 1,
"active_users": 0,
"active_users_cutoff": 0,
"image_id": 0,
"pinned_messages": [],
"admins": [],
"hidden_admins": [],
"moderators": [],
"hidden_moderators": [],
"read": true,
"default_read": true,
"default_accessible": true,
"write": true,
"default_write": true,
"upload": true,
"default_upload": true
}
"""
let roomData: Data = roomJson.data(using: .utf8)!
let result: OpenGroupAPI.Room = try! JSONDecoder().decode(OpenGroupAPI.Room.self, from: roomData)
expect(result.admin).to(beFalse())
expect(result.globalAdmin).to(beFalse())
expect(result.moderator).to(beFalse())
expect(result.globalModerator).to(beFalse())
}
it("sets the admin and moderator values when provided") {
let roomJson: String = """
{
"token": "testToken",
"name": "testName",
"description": "testDescription",
"info_updates": 0,
"message_sequence": 0,
"created": 1,
"active_users": 0,
"active_users_cutoff": 0,
"image_id": 0,
"pinned_messages": [],
"admin": true,
"global_admin": true,
"admins": [],
"hidden_admins": [],
"moderator": true,
"global_moderator": true,
"moderators": [],
"hidden_moderators": [],
"read": true,
"default_read": true,
"default_accessible": true,
"write": true,
"default_write": true,
"upload": true,
"default_upload": true
}
"""
let roomData: Data = roomJson.data(using: .utf8)!
let result: OpenGroupAPI.Room = try! JSONDecoder().decode(OpenGroupAPI.Room.self, from: roomData)
expect(result.admin).to(beTrue())
expect(result.globalAdmin).to(beTrue())
expect(result.moderator).to(beTrue())
expect(result.globalModerator).to(beTrue())
}
}
}
}
}

@ -0,0 +1,253 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class SOGSMessageSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a SOGSMessage") {
var messageJson: String!
var messageData: Data!
var decoder: JSONDecoder!
var testSign: TestSign!
var dependencies: Dependencies!
beforeEach {
messageJson = """
{
"id": 123,
"session_id": "05\(TestConstants.publicKey)",
"posted": 234,
"seqno": 345,
"whisper": false,
"whisper_mods": false,
"data": "VGVzdERhdGE=",
"signature": "VGVzdERhdGE="
}
"""
messageData = messageJson.data(using: .utf8)!
testSign = TestSign()
dependencies = Dependencies(
sign: testSign,
ed25519: TestEd25519.self
)
decoder = JSONDecoder()
decoder.userInfo = [ Dependencies.userInfoKey: dependencies as Any ]
}
context("when decoding") {
it("defaults the whisper values to false") {
messageJson = """
{
"id": 123,
"posted": 234,
"seqno": 345
}
"""
messageData = messageJson.data(using: .utf8)!
let result: OpenGroupAPI.Message? = try? decoder.decode(OpenGroupAPI.Message.self, from: messageData)
expect(result).toNot(beNil())
expect(result?.whisper).to(beFalse())
expect(result?.whisperMods).to(beFalse())
}
context("and there is no content") {
it("does not need a sender") {
messageJson = """
{
"id": 123,
"posted": 234,
"seqno": 345,
"whisper": false,
"whisper_mods": false
}
"""
messageData = messageJson.data(using: .utf8)!
let result: OpenGroupAPI.Message? = try? decoder.decode(OpenGroupAPI.Message.self, from: messageData)
expect(result).toNot(beNil())
expect(result?.sender).to(beNil())
expect(result?.base64EncodedData).to(beNil())
expect(result?.base64EncodedSignature).to(beNil())
}
}
context("and there is content") {
it("errors if there is no sender") {
messageJson = """
{
"id": 123,
"posted": 234,
"seqno": 345,
"whisper": false,
"whisper_mods": false,
"data": "VGVzdERhdGE=",
"signature": "VGVzdERhdGE="
}
"""
messageData = messageJson.data(using: .utf8)!
expect {
try decoder.decode(OpenGroupAPI.Message.self, from: messageData)
}
.to(throwError(HTTP.Error.parsingFailed))
}
it("errors if the data is not a base64 encoded string") {
messageJson = """
{
"id": 123,
"session_id": "05\(TestConstants.publicKey)",
"posted": 234,
"seqno": 345,
"whisper": false,
"whisper_mods": false,
"data": "Test!!!",
"signature": "VGVzdERhdGE="
}
"""
messageData = messageJson.data(using: .utf8)!
expect {
try decoder.decode(OpenGroupAPI.Message.self, from: messageData)
}
.to(throwError(HTTP.Error.parsingFailed))
}
it("errors if the signature is not a base64 encoded string") {
messageJson = """
{
"id": 123,
"session_id": "05\(TestConstants.publicKey)",
"posted": 234,
"seqno": 345,
"whisper": false,
"whisper_mods": false,
"data": "VGVzdERhdGE=",
"signature": "Test!!!"
}
"""
messageData = messageJson.data(using: .utf8)!
expect {
try decoder.decode(OpenGroupAPI.Message.self, from: messageData)
}
.to(throwError(HTTP.Error.parsingFailed))
}
it("errors if the dependencies are not provided to the JSONDecoder") {
decoder = JSONDecoder()
expect {
try decoder.decode(OpenGroupAPI.Message.self, from: messageData)
}
.to(throwError(HTTP.Error.parsingFailed))
}
it("errors if the session_id value is not valid") {
messageJson = """
{
"id": 123,
"session_id": "TestId",
"posted": 234,
"seqno": 345,
"whisper": false,
"whisper_mods": false,
"data": "VGVzdERhdGE=",
"signature": "VGVzdERhdGE="
}
"""
messageData = messageJson.data(using: .utf8)!
expect {
try decoder.decode(OpenGroupAPI.Message.self, from: messageData)
}
.to(throwError(HTTP.Error.parsingFailed))
}
context("that is blinded") {
beforeEach {
messageJson = """
{
"id": 123,
"session_id": "15\(TestConstants.publicKey)",
"posted": 234,
"seqno": 345,
"whisper": false,
"whisper_mods": false,
"data": "VGVzdERhdGE=",
"signature": "VGVzdERhdGE="
}
"""
messageData = messageJson.data(using: .utf8)!
}
it("succeeds if it succeeds verification") {
testSign.mockData[.verify] = true
expect {
try decoder.decode(OpenGroupAPI.Message.self, from: messageData)
}
.toNot(beNil())
}
it("throws if it fails verification") {
testSign.mockData[.verify] = false
expect {
try decoder.decode(OpenGroupAPI.Message.self, from: messageData)
}
.to(throwError(HTTP.Error.parsingFailed))
}
}
context("that is unblinded") {
it("succeeds if it succeeds verification") {
TestEd25519.mockData[
.verifySignature(
signature: Data(base64Encoded: "VGVzdERhdGE=")!,
publicKey: Data(hex: TestConstants.publicKey),
data: Data(base64Encoded: "VGVzdERhdGE=")!
)
] = true
expect {
try decoder.decode(OpenGroupAPI.Message.self, from: messageData)
}
.toNot(beNil())
}
it("throws if it fails verification") {
TestEd25519.mockData[
.verifySignature(
signature: Data(base64Encoded: "VGVzdERhdGE=")!,
publicKey: Data(hex: TestConstants.publicKey),
data: Data(base64Encoded: "VGVzdERhdGE=")!
)
] = false
expect {
try decoder.decode(OpenGroupAPI.Message.self, from: messageData)
}
.to(throwError(HTTP.Error.parsingFailed))
}
}
}
}
}
}
}

@ -0,0 +1,29 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class SendDirectMessageRequestSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a SendDirectMessageRequest") {
context("when encoding") {
it("encodes the data as a base64 string") {
let request: OpenGroupAPI.SendDirectMessageRequest = OpenGroupAPI.SendDirectMessageRequest(
message: "TestData".data(using: .utf8)!
)
let requestData: Data = try! JSONEncoder().encode(request)
let requestDataString: String = String(data: requestData, encoding: .utf8)!
expect(requestDataString).toNot(contain("TestData"))
expect(requestDataString).to(contain("VGVzdERhdGE="))
}
}
}
}
}

@ -0,0 +1,61 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class SendMessageRequestSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a SendMessageRequest") {
context("when initializing") {
it("defaults the optional values to nil") {
let request: OpenGroupAPI.SendMessageRequest = OpenGroupAPI.SendMessageRequest(
data: "TestData".data(using: .utf8)!,
signature: "TestSignature".data(using: .utf8)!
)
expect(request.whisperTo).to(beNil())
expect(request.whisperMods).to(beNil())
expect(request.fileIds).to(beNil())
}
}
context("when encoding") {
it("encodes the data as a base64 string") {
let request: OpenGroupAPI.SendMessageRequest = OpenGroupAPI.SendMessageRequest(
data: "TestData".data(using: .utf8)!,
signature: "TestSignature".data(using: .utf8)!,
whisperTo: nil,
whisperMods: nil,
fileIds: nil
)
let requestData: Data = try! JSONEncoder().encode(request)
let requestDataString: String = String(data: requestData, encoding: .utf8)!
expect(requestDataString).toNot(contain("TestData"))
expect(requestDataString).to(contain("VGVzdERhdGE="))
}
it("encodes the signature as a base64 string") {
let request: OpenGroupAPI.SendMessageRequest = OpenGroupAPI.SendMessageRequest(
data: "TestData".data(using: .utf8)!,
signature: "TestSignature".data(using: .utf8)!,
whisperTo: nil,
whisperMods: nil,
fileIds: nil
)
let requestData: Data = try! JSONEncoder().encode(request)
let requestDataString: String = String(data: requestData, encoding: .utf8)!
expect(requestDataString).toNot(contain("TestSignature"))
expect(requestDataString).to(contain("VGVzdFNpZ25hdHVyZQ=="))
}
}
}
}
}

@ -0,0 +1,44 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class UpdateMessageRequestSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a UpdateMessageRequest") {
context("when encoding") {
it("encodes the data as a base64 string") {
let request: OpenGroupAPI.UpdateMessageRequest = OpenGroupAPI.UpdateMessageRequest(
data: "TestData".data(using: .utf8)!,
signature: "TestSignature".data(using: .utf8)!,
fileIds: nil
)
let requestData: Data = try! JSONEncoder().encode(request)
let requestDataString: String = String(data: requestData, encoding: .utf8)!
expect(requestDataString).toNot(contain("TestData"))
expect(requestDataString).to(contain("VGVzdERhdGE="))
}
it("encodes the signature as a base64 string") {
let request: OpenGroupAPI.UpdateMessageRequest = OpenGroupAPI.UpdateMessageRequest(
data: "TestData".data(using: .utf8)!,
signature: "TestSignature".data(using: .utf8)!,
fileIds: nil
)
let requestData: Data = try! JSONEncoder().encode(request)
let requestDataString: String = String(data: requestData, encoding: .utf8)!
expect(requestDataString).toNot(contain("TestSignature"))
expect(requestDataString).to(contain("VGVzdFNpZ25hdHVyZQ=="))
}
}
}
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,26 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class NonceGeneratorSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a NonceGenerator16Byte") {
it("has the correct number of bytes") {
expect(OpenGroupAPI.NonceGenerator16Byte().NonceBytes).to(equal(16))
}
}
describe("a NonceGenerator24Byte") {
it("has the correct number of bytes") {
expect(OpenGroupAPI.NonceGenerator24Byte().NonceBytes).to(equal(24))
}
}
}
}

@ -0,0 +1,23 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class PersonalizationSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a Personalization") {
it("generates bytes correctly") {
expect(OpenGroupAPI.Personalization.sharedKeys.bytes)
.to(equal([115, 111, 103, 115, 46, 115, 104, 97, 114, 101, 100, 95, 107, 101, 121, 115]))
expect(OpenGroupAPI.Personalization.authHeader.bytes)
.to(equal([115, 111, 103, 115, 46, 97, 117, 116, 104, 95, 104, 101, 97, 100, 101, 114]))
}
}
}
}

@ -0,0 +1,67 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class SOGSEndpointSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a SOGSEndpoint") {
it("generates the path value correctly") {
// Utility
expect(OpenGroupAPI.Endpoint.onion.path).to(equal("oxen/v4/lsrpc"))
expect(OpenGroupAPI.Endpoint.batch.path).to(equal("batch"))
expect(OpenGroupAPI.Endpoint.sequence.path).to(equal("sequence"))
expect(OpenGroupAPI.Endpoint.capabilities.path).to(equal("capabilities"))
// Rooms
expect(OpenGroupAPI.Endpoint.rooms.path).to(equal("rooms"))
expect(OpenGroupAPI.Endpoint.room("test").path).to(equal("room/test"))
expect(OpenGroupAPI.Endpoint.roomPollInfo("test", 123).path).to(equal("room/test/pollInfo/123"))
// Messages
expect(OpenGroupAPI.Endpoint.roomMessage("test").path).to(equal("room/test/message"))
expect(OpenGroupAPI.Endpoint.roomMessageIndividual("test", id: 123).path).to(equal("room/test/message/123"))
expect(OpenGroupAPI.Endpoint.roomMessagesRecent("test").path).to(equal("room/test/messages/recent"))
expect(OpenGroupAPI.Endpoint.roomMessagesBefore("test", id: 123).path).to(equal("room/test/messages/before/123"))
expect(OpenGroupAPI.Endpoint.roomMessagesSince("test", seqNo: 123).path)
.to(equal("room/test/messages/since/123"))
// Pinning
expect(OpenGroupAPI.Endpoint.roomPinMessage("test", id: 123).path).to(equal("room/test/pin/123"))
expect(OpenGroupAPI.Endpoint.roomUnpinMessage("test", id: 123).path).to(equal("room/test/unpin/123"))
expect(OpenGroupAPI.Endpoint.roomUnpinAll("test").path).to(equal("room/test/unpin/all"))
// Files
expect(OpenGroupAPI.Endpoint.roomFile("test").path).to(equal("room/test/file"))
expect(OpenGroupAPI.Endpoint.roomFileIndividual("test", 123).path).to(equal("room/test/file/123"))
// Inbox/Outbox (Message Requests)
expect(OpenGroupAPI.Endpoint.inbox.path).to(equal("inbox"))
expect(OpenGroupAPI.Endpoint.inboxSince(id: 123).path).to(equal("inbox/since/123"))
expect(OpenGroupAPI.Endpoint.inboxFor(sessionId: "test").path).to(equal("inbox/test"))
expect(OpenGroupAPI.Endpoint.outbox.path).to(equal("outbox"))
expect(OpenGroupAPI.Endpoint.outboxSince(id: 123).path).to(equal("outbox/since/123"))
// Users
expect(OpenGroupAPI.Endpoint.userBan("test").path).to(equal("user/test/ban"))
expect(OpenGroupAPI.Endpoint.userUnban("test").path).to(equal("user/test/unban"))
expect(OpenGroupAPI.Endpoint.userModerator("test").path).to(equal("user/test/moderator"))
expect(OpenGroupAPI.Endpoint.userDeleteMessages("test").path).to(equal("user/test/deleteMessages"))
}
}
}
}

@ -0,0 +1,25 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class SOGSErrorSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("a SOGSError") {
it("generates the error description correctly") {
expect(OpenGroupAPI.Error.decryptionFailed.errorDescription)
.to(equal("Couldn't decrypt response."))
expect(OpenGroupAPI.Error.signingFailed.errorDescription)
.to(equal("Couldn't sign message."))
expect(OpenGroupAPI.Error.noPublicKey.errorDescription)
.to(equal("Couldn't find server public key."))
}
}
}
}

@ -0,0 +1,47 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import Quick
import Nimble
@testable import SessionMessagingKit
class SodiumProtocolsSpec: QuickSpec {
// MARK: - Spec
override func spec() {
describe("an AeadXChaCha20Poly1305IetfType") {
let testValue: [UInt8] = [1, 2, 3]
it("provides the default values in it's extensions") {
let testAead: TestAeadXChaCha20Poly1305Ietf = TestAeadXChaCha20Poly1305Ietf()
testAead.mockData[.encrypt] = testValue
testAead.mockData[.decrypt] = testValue
expect(testAead.encrypt(message: [], secretKey: [], nonce: [])).to(equal(testValue))
expect(testAead.encrypt(message: [], secretKey: [], nonce: [], additionalData: nil)).to(equal(testValue))
expect(testAead.decrypt(authenticatedCipherText: [], secretKey: [], nonce: [])).to(equal(testValue))
expect(testAead.decrypt(authenticatedCipherText: [], secretKey: [], nonce: [], additionalData: nil))
.to(equal(testValue))
}
}
describe("a GenericHashType") {
let testValue: [UInt8] = [1, 2, 3]
it("provides the default values in it's extensions") {
let testGenericHash: TestGenericHash = TestGenericHash()
testGenericHash.mockData[.hash] = testValue
testGenericHash.mockData[.hashSaltPersonal] = testValue
expect(testGenericHash.hash(message: [])).to(equal(testValue))
expect(testGenericHash.hash(message: [], key: nil)).to(equal(testValue))
expect(testGenericHash.hashSaltPersonal(message: [], outputLength: 0, salt: [], personal: []))
.to(equal(testValue))
expect(testGenericHash.hashSaltPersonal(message: [], outputLength: 0, key: nil, salt: [], personal: []))
.to(equal(testValue))
}
}
}
}

@ -21,6 +21,7 @@ class TestStorage: SessionMessagingKitStorageProtocol, Mockable {
case openGroupSequenceNumber case openGroupSequenceNumber
case openGroupInboxLatestMessageId case openGroupInboxLatestMessageId
case openGroupOutboxLatestMessageId case openGroupOutboxLatestMessageId
case receivedMessageTimestamp
} }
typealias Key = DataKey typealias Key = DataKey
@ -176,8 +177,14 @@ class TestStorage: SessionMessagingKitStorageProtocol, Mockable {
func getAllMessageRequestThreads() -> [String: TSContactThread] { return [:] } func getAllMessageRequestThreads() -> [String: TSContactThread] { return [:] }
func getAllMessageRequestThreads(using transaction: YapDatabaseReadTransaction) -> [String: TSContactThread] { return [:] } func getAllMessageRequestThreads(using transaction: YapDatabaseReadTransaction) -> [String: TSContactThread] { return [:] }
func getReceivedMessageTimestamps(using transaction: Any) -> [UInt64] { return [] } func getReceivedMessageTimestamps(using transaction: Any) -> [UInt64] {
func addReceivedMessageTimestamp(_ timestamp: UInt64, using transaction: Any) {} return ((mockData[.receivedMessageTimestamp] as? UInt64).map { [$0] } ?? [])
}
func addReceivedMessageTimestamp(_ timestamp: UInt64, using transaction: Any) {
mockData[.receivedMessageTimestamp] = timestamp
}
func getOrCreateThread(for publicKey: String, groupPublicKey: String?, openGroupID: String?, using transaction: Any) -> String? { return nil } func getOrCreateThread(for publicKey: String, groupPublicKey: String?, openGroupID: String?, using transaction: Any) -> String? { return nil }
func persist(_ message: VisibleMessage, quotedMessage: TSQuotedMessage?, linkPreview: OWSLinkPreview?, groupPublicKey: String?, openGroupID: String?, using transaction: Any) -> String? { return nil } func persist(_ message: VisibleMessage, quotedMessage: TSQuotedMessage?, linkPreview: OWSLinkPreview?, groupPublicKey: String?, openGroupID: String?, using transaction: Any) -> String? { return nil }
func persist(_ attachments: [VisibleMessage.Attachment], using transaction: Any) -> [String] { return [] } func persist(_ attachments: [VisibleMessage.Attachment], using transaction: Any) -> [String] { return [] }

Loading…
Cancel
Save