diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index 31b23d4f7c..9768553729 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 0900555621E4A96E0030924C /* Wallpaper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0900555521E4A96D0030924C /* Wallpaper.swift */; }; 09028386218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09028385218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift */; }; + 090E778322A9862100CD99F5 /* ChannelOwnershipTransfer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 090E778222A9862100CD99F5 /* ChannelOwnershipTransfer.swift */; }; 093857A82243D87900EB6A54 /* ManagedSynchronizeEmojiKeywordsOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093857A62243D87800EB6A54 /* ManagedSynchronizeEmojiKeywordsOperations.swift */; }; 093857A92243D87900EB6A54 /* SynchronizeEmojiKeywordsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093857A72243D87900EB6A54 /* SynchronizeEmojiKeywordsOperation.swift */; }; 093857AB2243D88D00EB6A54 /* EmojiKeywords.swift in Sources */ = {isa = PBXBuildFile; fileRef = 093857AA2243D88C00EB6A54 /* EmojiKeywords.swift */; }; @@ -829,6 +830,7 @@ /* Begin PBXFileReference section */ 0900555521E4A96D0030924C /* Wallpaper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wallpaper.swift; sourceTree = ""; }; 09028385218E5DBB0067EFBD /* ManagedVoipConfigurationUpdates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedVoipConfigurationUpdates.swift; sourceTree = ""; }; + 090E778222A9862100CD99F5 /* ChannelOwnershipTransfer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelOwnershipTransfer.swift; sourceTree = ""; }; 093857A62243D87800EB6A54 /* ManagedSynchronizeEmojiKeywordsOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeEmojiKeywordsOperations.swift; sourceTree = ""; }; 093857A72243D87900EB6A54 /* SynchronizeEmojiKeywordsOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeEmojiKeywordsOperation.swift; sourceTree = ""; }; 093857AA2243D88C00EB6A54 /* EmojiKeywords.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmojiKeywords.swift; sourceTree = ""; }; @@ -2004,6 +2006,7 @@ D0633CD12253A528003DD95F /* ChatOnlineMembers.swift */, D015E00D225CA61100CB9E8A /* FindChannelById.swift */, D076F8882296D8E9004F895A /* ManageChannelDiscussionGroup.swift */, + 090E778222A9862100CD99F5 /* ChannelOwnershipTransfer.swift */, ); name = Peers; sourceTree = ""; @@ -2171,6 +2174,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = D09D8BF71D4FAB1D0081DBEC; @@ -2234,6 +2238,7 @@ D00D34451E6EDD420057B307 /* SynchronizeConsumeMessageContentsOperation.swift in Sources */, D02D60AB206BA64100FEFE1E /* VerifySecureIdValue.swift in Sources */, D00D343F1E6ED6E50057B307 /* ConsumableContentMessageAttribute.swift in Sources */, + 090E778322A9862100CD99F5 /* ChannelOwnershipTransfer.swift in Sources */, D03B0CE01D62249100955575 /* StoreMessage_Telegram.swift in Sources */, D08774FE1E3E3A3500A97350 /* GlobalNotificationSettings.swift in Sources */, D023E67821540624008C27D1 /* UpdateMessageMedia.swift in Sources */, diff --git a/TelegramCore/ChannelOwnershipTransfer.swift b/TelegramCore/ChannelOwnershipTransfer.swift new file mode 100644 index 0000000000..55a24eddfb --- /dev/null +++ b/TelegramCore/ChannelOwnershipTransfer.swift @@ -0,0 +1,84 @@ +import Foundation +#if os(macOS) +import SwiftSignalKitMac +import PostboxMac +#else +import SwiftSignalKit +import Postbox +#endif + +public enum ChannelOwnershipTransferError { + case generic + case twoStepAuthMissing + case twoStepAuthTooFresh(Int32) + case authSessionTooFresh(Int32) + case requestPassword + case invalidPassword +} + +public func updateChannelOwnership(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, channelId: PeerId, memberId: PeerId, password: String?) -> Signal { + return postbox.transaction { transaction -> (channel: Peer?, user: Peer?) in + return (channel: transaction.getPeer(channelId), user: transaction.getPeer(memberId)) + } + |> introduceError(ChannelOwnershipTransferError.self) + |> mapToSignal { channel, user -> Signal in + guard let channel = channel, let user = user else { + return .fail(.generic) + } + guard let apiChannel = apiInputChannel(channel) else { + return .fail(.generic) + } + guard let apiUser = apiInputUser(user) else { + return .fail(.generic) + } + + let checkPassword: Signal + if let password = password, !password.isEmpty { + checkPassword = twoStepAuthData(network) + |> mapError { _ in ChannelOwnershipTransferError.generic } + |> mapToSignal { authData -> Signal in + if let currentPasswordDerivation = authData.currentPasswordDerivation, let srpSessionData = authData.srpSessionData { + guard let kdfResult = passwordKDF(password: password, derivation: currentPasswordDerivation, srpSessionData: srpSessionData) else { + return .fail(.generic) + } + return .single(.inputCheckPasswordSRP(srpId: kdfResult.id, A: Buffer(data: kdfResult.A), M1: Buffer(data: kdfResult.M1))) + } else { + return .fail(.twoStepAuthMissing) + } + } + } else { + checkPassword = .single(.inputCheckPasswordEmpty) + } + + return checkPassword + |> mapToSignal { password -> Signal in + return network.request(Api.functions.channels.editCreator(channel: apiChannel, userId: apiUser, password: password)) + |> mapError { error -> ChannelOwnershipTransferError in + if error.errorDescription == "PASSWORD_HASH_INVALID" { + if case .inputCheckPasswordEmpty = password { + return .requestPassword + } else { + return .invalidPassword + } + } else if error.errorDescription == "PASSWORD_MISSING" { + return .twoStepAuthMissing + } else if error.errorDescription.hasPrefix("PASSWORD_TOO_FRESH_") { + let timeout = String(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "PASSWORD_TOO_FRESH_".count)...]) + if let value = Int32(timeout) { + return .twoStepAuthTooFresh(value) + } + } else if error.errorDescription.hasPrefix("SESSION_TOO_FRESH_") { + let timeout = String(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "SESSION_TOO_FRESH_".count)...]) + if let value = Int32(timeout) { + return .authSessionTooFresh(value) + } + } + return .generic + } + |> mapToSignal { updates -> Signal in + accountStateManager.addUpdates(updates) + return.complete() + } + } + } +} diff --git a/TelegramCore/ManageChannelDiscussionGroup.swift b/TelegramCore/ManageChannelDiscussionGroup.swift index c77dbce8f8..41a3bf19c9 100644 --- a/TelegramCore/ManageChannelDiscussionGroup.swift +++ b/TelegramCore/ManageChannelDiscussionGroup.swift @@ -7,7 +7,6 @@ import SwiftSignalKit import Postbox #endif - public enum AvailableChannelDiscussionGroupError { case generic }