mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
no message
This commit is contained in:
@@ -362,6 +362,16 @@
|
|||||||
D08F4A671E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */; };
|
D08F4A671E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */; };
|
||||||
D08F4A691E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */; };
|
D08F4A691E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */; };
|
||||||
D08F4A6A1E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */; };
|
D08F4A6A1E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */; };
|
||||||
|
D093D7EB206413C900BC3599 /* SecureIdPassportIdentity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7EA206413C900BC3599 /* SecureIdPassportIdentity.swift */; };
|
||||||
|
D093D7EC206413C900BC3599 /* SecureIdPassportIdentity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7EA206413C900BC3599 /* SecureIdPassportIdentity.swift */; };
|
||||||
|
D093D7EE206413F600BC3599 /* SecureIdDataTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7ED206413F600BC3599 /* SecureIdDataTypes.swift */; };
|
||||||
|
D093D7EF206413F600BC3599 /* SecureIdDataTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7ED206413F600BC3599 /* SecureIdDataTypes.swift */; };
|
||||||
|
D093D7F12064194600BC3599 /* SecureIdIdentityField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F02064194600BC3599 /* SecureIdIdentityField.swift */; };
|
||||||
|
D093D7F22064194600BC3599 /* SecureIdIdentityField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F02064194600BC3599 /* SecureIdIdentityField.swift */; };
|
||||||
|
D093D7F520641A4900BC3599 /* SecureIdPhoneField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F420641A4900BC3599 /* SecureIdPhoneField.swift */; };
|
||||||
|
D093D7F620641A4900BC3599 /* SecureIdPhoneField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F420641A4900BC3599 /* SecureIdPhoneField.swift */; };
|
||||||
|
D093D7F920641AA500BC3599 /* SecureIdEmailField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F820641AA500BC3599 /* SecureIdEmailField.swift */; };
|
||||||
|
D093D7FA20641AA500BC3599 /* SecureIdEmailField.swift in Sources */ = {isa = PBXBuildFile; fileRef = D093D7F820641AA500BC3599 /* SecureIdEmailField.swift */; };
|
||||||
D099D7461EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099D7451EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift */; };
|
D099D7461EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099D7451EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift */; };
|
||||||
D099D7471EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099D7451EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift */; };
|
D099D7471EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099D7451EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift */; };
|
||||||
D099D7491EEF418D00A3128C /* HistoryViewChannelStateValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099D7481EEF418D00A3128C /* HistoryViewChannelStateValidation.swift */; };
|
D099D7491EEF418D00A3128C /* HistoryViewChannelStateValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099D7481EEF418D00A3128C /* HistoryViewChannelStateValidation.swift */; };
|
||||||
@@ -499,6 +509,8 @@
|
|||||||
D0BE303B20619EE800FBE6D8 /* SecureIdForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE303920619EE800FBE6D8 /* SecureIdForm.swift */; };
|
D0BE303B20619EE800FBE6D8 /* SecureIdForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE303920619EE800FBE6D8 /* SecureIdForm.swift */; };
|
||||||
D0BE303D2061A29100FBE6D8 /* RequestSecureIdForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */; };
|
D0BE303D2061A29100FBE6D8 /* RequestSecureIdForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */; };
|
||||||
D0BE303E2061A29100FBE6D8 /* RequestSecureIdForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */; };
|
D0BE303E2061A29100FBE6D8 /* RequestSecureIdForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */; };
|
||||||
|
D0BE304B20627D9800FBE6D8 /* AccessSecureId.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE304A20627D9800FBE6D8 /* AccessSecureId.swift */; };
|
||||||
|
D0BE304C20627D9800FBE6D8 /* AccessSecureId.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE304A20627D9800FBE6D8 /* AccessSecureId.swift */; };
|
||||||
D0BE383E1E7C5995000079AF /* MediaPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE383D1E7C5995000079AF /* MediaPool.swift */; };
|
D0BE383E1E7C5995000079AF /* MediaPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE383D1E7C5995000079AF /* MediaPool.swift */; };
|
||||||
D0BE383F1E7C5995000079AF /* MediaPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE383D1E7C5995000079AF /* MediaPool.swift */; };
|
D0BE383F1E7C5995000079AF /* MediaPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE383D1E7C5995000079AF /* MediaPool.swift */; };
|
||||||
D0BEAF5D1E54941B00BD963D /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5C1E54941B00BD963D /* Authorization.swift */; };
|
D0BEAF5D1E54941B00BD963D /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF5C1E54941B00BD963D /* Authorization.swift */; };
|
||||||
@@ -840,6 +852,11 @@
|
|||||||
D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Localizations.swift; sourceTree = "<group>"; };
|
D08CAA8B1ED81EDF0000FDA8 /* Localizations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Localizations.swift; sourceTree = "<group>"; };
|
||||||
D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
|
D08F4A651E79CC4A00A2AA15 /* SynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
|
||||||
D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
|
D08F4A681E79CECB00A2AA15 /* ManagedSynchronizeInstalledStickerPacksOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeInstalledStickerPacksOperations.swift; sourceTree = "<group>"; };
|
||||||
|
D093D7EA206413C900BC3599 /* SecureIdPassportIdentity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdPassportIdentity.swift; sourceTree = "<group>"; };
|
||||||
|
D093D7ED206413F600BC3599 /* SecureIdDataTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdDataTypes.swift; sourceTree = "<group>"; };
|
||||||
|
D093D7F02064194600BC3599 /* SecureIdIdentityField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdIdentityField.swift; sourceTree = "<group>"; };
|
||||||
|
D093D7F420641A4900BC3599 /* SecureIdPhoneField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdPhoneField.swift; sourceTree = "<group>"; };
|
||||||
|
D093D7F820641AA500BC3599 /* SecureIdEmailField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdEmailField.swift; sourceTree = "<group>"; };
|
||||||
D099D7451EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelMessageStateVersionAttribute.swift; sourceTree = "<group>"; };
|
D099D7451EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelMessageStateVersionAttribute.swift; sourceTree = "<group>"; };
|
||||||
D099D7481EEF418D00A3128C /* HistoryViewChannelStateValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryViewChannelStateValidation.swift; sourceTree = "<group>"; };
|
D099D7481EEF418D00A3128C /* HistoryViewChannelStateValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryViewChannelStateValidation.swift; sourceTree = "<group>"; };
|
||||||
D099EA1B1DE72867001AF5A8 /* PeerCommands.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerCommands.swift; sourceTree = "<group>"; };
|
D099EA1B1DE72867001AF5A8 /* PeerCommands.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerCommands.swift; sourceTree = "<group>"; };
|
||||||
@@ -922,6 +939,7 @@
|
|||||||
D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TogglePeerChatPinned.swift; sourceTree = "<group>"; };
|
D0BC387A1E40D2880044D6FE /* TogglePeerChatPinned.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TogglePeerChatPinned.swift; sourceTree = "<group>"; };
|
||||||
D0BE303920619EE800FBE6D8 /* SecureIdForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdForm.swift; sourceTree = "<group>"; };
|
D0BE303920619EE800FBE6D8 /* SecureIdForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdForm.swift; sourceTree = "<group>"; };
|
||||||
D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestSecureIdForm.swift; sourceTree = "<group>"; };
|
D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestSecureIdForm.swift; sourceTree = "<group>"; };
|
||||||
|
D0BE304A20627D9800FBE6D8 /* AccessSecureId.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessSecureId.swift; sourceTree = "<group>"; };
|
||||||
D0BE383D1E7C5995000079AF /* MediaPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaPool.swift; sourceTree = "<group>"; };
|
D0BE383D1E7C5995000079AF /* MediaPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaPool.swift; sourceTree = "<group>"; };
|
||||||
D0BEAF5C1E54941B00BD963D /* Authorization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Authorization.swift; sourceTree = "<group>"; };
|
D0BEAF5C1E54941B00BD963D /* Authorization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Authorization.swift; sourceTree = "<group>"; };
|
||||||
D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountManager.swift; sourceTree = "<group>"; };
|
D0BEAF5F1E54ACF900BD963D /* AccountManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountManager.swift; sourceTree = "<group>"; };
|
||||||
@@ -1479,6 +1497,42 @@
|
|||||||
name = Localization;
|
name = Localization;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D093D7E82064135300BC3599 /* Fields */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D093D7ED206413F600BC3599 /* SecureIdDataTypes.swift */,
|
||||||
|
D093D7E92064135A00BC3599 /* Identity */,
|
||||||
|
D093D7F320641A3F00BC3599 /* Phone */,
|
||||||
|
D093D7F720641A9600BC3599 /* Email */,
|
||||||
|
);
|
||||||
|
name = Fields;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
D093D7E92064135A00BC3599 /* Identity */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D093D7F02064194600BC3599 /* SecureIdIdentityField.swift */,
|
||||||
|
D093D7EA206413C900BC3599 /* SecureIdPassportIdentity.swift */,
|
||||||
|
);
|
||||||
|
name = Identity;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
D093D7F320641A3F00BC3599 /* Phone */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D093D7F420641A4900BC3599 /* SecureIdPhoneField.swift */,
|
||||||
|
);
|
||||||
|
name = Phone;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
D093D7F720641A9600BC3599 /* Email */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D093D7F820641AA500BC3599 /* SecureIdEmailField.swift */,
|
||||||
|
);
|
||||||
|
name = Email;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D09D8BF71D4FAB1D0081DBEC = {
|
D09D8BF71D4FAB1D0081DBEC = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -1569,6 +1623,8 @@
|
|||||||
children = (
|
children = (
|
||||||
D0BE303920619EE800FBE6D8 /* SecureIdForm.swift */,
|
D0BE303920619EE800FBE6D8 /* SecureIdForm.swift */,
|
||||||
D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */,
|
D0BE303C2061A29100FBE6D8 /* RequestSecureIdForm.swift */,
|
||||||
|
D0BE304A20627D9800FBE6D8 /* AccessSecureId.swift */,
|
||||||
|
D093D7E82064135300BC3599 /* Fields */,
|
||||||
);
|
);
|
||||||
name = "Secure ID";
|
name = "Secure ID";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1848,6 +1904,7 @@
|
|||||||
D021E0DF1DB539FC00C6B04F /* StickerPack.swift in Sources */,
|
D021E0DF1DB539FC00C6B04F /* StickerPack.swift in Sources */,
|
||||||
D03B0D091D62255C00955575 /* EnqueueMessage.swift in Sources */,
|
D03B0D091D62255C00955575 /* EnqueueMessage.swift in Sources */,
|
||||||
D0DFD5DF1FCDBCFD0039B3B1 /* CachedSentMediaReferences.swift in Sources */,
|
D0DFD5DF1FCDBCFD0039B3B1 /* CachedSentMediaReferences.swift in Sources */,
|
||||||
|
D093D7EE206413F600BC3599 /* SecureIdDataTypes.swift in Sources */,
|
||||||
D00D343C1E6EC9770057B307 /* TelegramMediaGame.swift in Sources */,
|
D00D343C1E6EC9770057B307 /* TelegramMediaGame.swift in Sources */,
|
||||||
D033FEB01E61EB0200644997 /* PeerReportStatus.swift in Sources */,
|
D033FEB01E61EB0200644997 /* PeerReportStatus.swift in Sources */,
|
||||||
D050F2511E4A59C200988324 /* JoinLink.swift in Sources */,
|
D050F2511E4A59C200988324 /* JoinLink.swift in Sources */,
|
||||||
@@ -1895,6 +1952,7 @@
|
|||||||
D0DF0CA81D82BF32008AEB01 /* PeerParticipants.swift in Sources */,
|
D0DF0CA81D82BF32008AEB01 /* PeerParticipants.swift in Sources */,
|
||||||
D0FA8BA71E1FA6DF001E855B /* TelegramSecretChat.swift in Sources */,
|
D0FA8BA71E1FA6DF001E855B /* TelegramSecretChat.swift in Sources */,
|
||||||
D03B0D5F1D631A6900955575 /* Serialization.swift in Sources */,
|
D03B0D5F1D631A6900955575 /* Serialization.swift in Sources */,
|
||||||
|
D093D7F920641AA500BC3599 /* SecureIdEmailField.swift in Sources */,
|
||||||
D0C44B611FC616E200227BE0 /* SearchGroupMembers.swift in Sources */,
|
D0C44B611FC616E200227BE0 /* SearchGroupMembers.swift in Sources */,
|
||||||
D03B0D441D6319F900955575 /* CloudFileMediaResource.swift in Sources */,
|
D03B0D441D6319F900955575 /* CloudFileMediaResource.swift in Sources */,
|
||||||
D018D3371E648ACF00C5E089 /* CreateChannel.swift in Sources */,
|
D018D3371E648ACF00C5E089 /* CreateChannel.swift in Sources */,
|
||||||
@@ -1988,6 +2046,7 @@
|
|||||||
D0F7AB2C1DCE889D009AD9A1 /* EditedMessageAttribute.swift in Sources */,
|
D0F7AB2C1DCE889D009AD9A1 /* EditedMessageAttribute.swift in Sources */,
|
||||||
D0FA8BAA1E1FB76E001E855B /* ManagedSecretChatOutgoingOperations.swift in Sources */,
|
D0FA8BAA1E1FB76E001E855B /* ManagedSecretChatOutgoingOperations.swift in Sources */,
|
||||||
D00D97C71E32901700E5C2B6 /* PeerInputActivity.swift in Sources */,
|
D00D97C71E32901700E5C2B6 /* PeerInputActivity.swift in Sources */,
|
||||||
|
D093D7EB206413C900BC3599 /* SecureIdPassportIdentity.swift in Sources */,
|
||||||
D0FA8BAD1E1FD6E2001E855B /* MemoryBufferExtensions.swift in Sources */,
|
D0FA8BAD1E1FD6E2001E855B /* MemoryBufferExtensions.swift in Sources */,
|
||||||
D03B0CBF1D62234A00955575 /* Log.swift in Sources */,
|
D03B0CBF1D62234A00955575 /* Log.swift in Sources */,
|
||||||
C2FD33E41E687BF1008D13D4 /* PeerPhotoUpdater.swift in Sources */,
|
C2FD33E41E687BF1008D13D4 /* PeerPhotoUpdater.swift in Sources */,
|
||||||
@@ -2023,6 +2082,7 @@
|
|||||||
D033FEB61E61F3F900644997 /* BlockedPeers.swift in Sources */,
|
D033FEB61E61F3F900644997 /* BlockedPeers.swift in Sources */,
|
||||||
D00C7CCC1E3620C30080C3D5 /* CachedChannelParticipants.swift in Sources */,
|
D00C7CCC1E3620C30080C3D5 /* CachedChannelParticipants.swift in Sources */,
|
||||||
D09BB6B41DB02C2B00A905C0 /* PendingMessageManager.swift in Sources */,
|
D09BB6B41DB02C2B00A905C0 /* PendingMessageManager.swift in Sources */,
|
||||||
|
D093D7F520641A4900BC3599 /* SecureIdPhoneField.swift in Sources */,
|
||||||
D0B167231F9F972E00976B40 /* LoggingSettings.swift in Sources */,
|
D0B167231F9F972E00976B40 /* LoggingSettings.swift in Sources */,
|
||||||
D0BC387B1E40D2880044D6FE /* TogglePeerChatPinned.swift in Sources */,
|
D0BC387B1E40D2880044D6FE /* TogglePeerChatPinned.swift in Sources */,
|
||||||
D0BB7C5A1E5C8074001527C3 /* ChannelParticipants.swift in Sources */,
|
D0BB7C5A1E5C8074001527C3 /* ChannelParticipants.swift in Sources */,
|
||||||
@@ -2038,6 +2098,7 @@
|
|||||||
D01C7ED31EF5DF83008305F1 /* LimitsConfiguration.swift in Sources */,
|
D01C7ED31EF5DF83008305F1 /* LimitsConfiguration.swift in Sources */,
|
||||||
D0F02CE51E9926C40065DEE2 /* ManagedConfigurationUpdates.swift in Sources */,
|
D0F02CE51E9926C40065DEE2 /* ManagedConfigurationUpdates.swift in Sources */,
|
||||||
D0528E6A1E65DD2100E2FEF5 /* WebpagePreview.swift in Sources */,
|
D0528E6A1E65DD2100E2FEF5 /* WebpagePreview.swift in Sources */,
|
||||||
|
D0BE304B20627D9800FBE6D8 /* AccessSecureId.swift in Sources */,
|
||||||
D0BEAF5D1E54941B00BD963D /* Authorization.swift in Sources */,
|
D0BEAF5D1E54941B00BD963D /* Authorization.swift in Sources */,
|
||||||
D0C26D6C1FE286C3004ABF18 /* FetchChatList.swift in Sources */,
|
D0C26D6C1FE286C3004ABF18 /* FetchChatList.swift in Sources */,
|
||||||
D0B843831DA6EDB8005F29E1 /* CachedGroupData.swift in Sources */,
|
D0B843831DA6EDB8005F29E1 /* CachedGroupData.swift in Sources */,
|
||||||
@@ -2095,6 +2156,7 @@
|
|||||||
D021E0E21DB5401A00C6B04F /* StickerManagement.swift in Sources */,
|
D021E0E21DB5401A00C6B04F /* StickerManagement.swift in Sources */,
|
||||||
D0BC38701E40853E0044D6FE /* UpdatePeers.swift in Sources */,
|
D0BC38701E40853E0044D6FE /* UpdatePeers.swift in Sources */,
|
||||||
D0F3A8A81E82CD7D00B4C64C /* UpdatePeerChatInterfaceState.swift in Sources */,
|
D0F3A8A81E82CD7D00B4C64C /* UpdatePeerChatInterfaceState.swift in Sources */,
|
||||||
|
D093D7F12064194600BC3599 /* SecureIdIdentityField.swift in Sources */,
|
||||||
D03B0CE21D62249B00955575 /* InlineBotMessageAttribute.swift in Sources */,
|
D03B0CE21D62249B00955575 /* InlineBotMessageAttribute.swift in Sources */,
|
||||||
D0AB0B9A1D666520002C78E7 /* ManagedSynchronizePeerReadStates.swift in Sources */,
|
D0AB0B9A1D666520002C78E7 /* ManagedSynchronizePeerReadStates.swift in Sources */,
|
||||||
D03B0D5B1D631A6900955575 /* Buffer.swift in Sources */,
|
D03B0D5B1D631A6900955575 /* Buffer.swift in Sources */,
|
||||||
@@ -2161,6 +2223,7 @@
|
|||||||
C26A37EF1E5E0C41006977AC /* ChannelParticipants.swift in Sources */,
|
C26A37EF1E5E0C41006977AC /* ChannelParticipants.swift in Sources */,
|
||||||
D00D343D1E6EC9770057B307 /* TelegramMediaGame.swift in Sources */,
|
D00D343D1E6EC9770057B307 /* TelegramMediaGame.swift in Sources */,
|
||||||
D0C26D6A1FE02402004ABF18 /* ManagedSynchronizeGroupedPeersOperations.swift in Sources */,
|
D0C26D6A1FE02402004ABF18 /* ManagedSynchronizeGroupedPeersOperations.swift in Sources */,
|
||||||
|
D093D7F22064194600BC3599 /* SecureIdIdentityField.swift in Sources */,
|
||||||
D01C7F051EFC1C49008305F1 /* DeviceContact.swift in Sources */,
|
D01C7F051EFC1C49008305F1 /* DeviceContact.swift in Sources */,
|
||||||
D050F26A1E4A5B6D00988324 /* ManagedGlobalNotificationSettings.swift in Sources */,
|
D050F26A1E4A5B6D00988324 /* ManagedGlobalNotificationSettings.swift in Sources */,
|
||||||
D050F26B1E4A5B6D00988324 /* ApplyMaxReadIndexInteractively.swift in Sources */,
|
D050F26B1E4A5B6D00988324 /* ApplyMaxReadIndexInteractively.swift in Sources */,
|
||||||
@@ -2252,6 +2315,7 @@
|
|||||||
D0BEAF611E54ACF900BD963D /* AccountManager.swift in Sources */,
|
D0BEAF611E54ACF900BD963D /* AccountManager.swift in Sources */,
|
||||||
D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */,
|
D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */,
|
||||||
D0B8442B1DAB91E0005F29E1 /* NBMetadataCore.m in Sources */,
|
D0B8442B1DAB91E0005F29E1 /* NBMetadataCore.m in Sources */,
|
||||||
|
D093D7EF206413F600BC3599 /* SecureIdDataTypes.swift in Sources */,
|
||||||
D03DC9141F82F89D001D584C /* RegularChatState.swift in Sources */,
|
D03DC9141F82F89D001D584C /* RegularChatState.swift in Sources */,
|
||||||
D0C44B621FC616E200227BE0 /* SearchGroupMembers.swift in Sources */,
|
D0C44B621FC616E200227BE0 /* SearchGroupMembers.swift in Sources */,
|
||||||
D00C7CD01E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */,
|
D00C7CD01E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */,
|
||||||
@@ -2280,8 +2344,10 @@
|
|||||||
D0B8442A1DAB91E0005F29E1 /* NBAsYouTypeFormatter.m in Sources */,
|
D0B8442A1DAB91E0005F29E1 /* NBAsYouTypeFormatter.m in Sources */,
|
||||||
D07047B51F3DF1FE00F6A8D4 /* ConsumablePersonalMentionMessageAttribute.swift in Sources */,
|
D07047B51F3DF1FE00F6A8D4 /* ConsumablePersonalMentionMessageAttribute.swift in Sources */,
|
||||||
D0448C8F1E22993C005A61A7 /* ProcessSecretChatIncomingDecryptedOperations.swift in Sources */,
|
D0448C8F1E22993C005A61A7 /* ProcessSecretChatIncomingDecryptedOperations.swift in Sources */,
|
||||||
|
D093D7F620641A4900BC3599 /* SecureIdPhoneField.swift in Sources */,
|
||||||
D0C26D6D1FE286C3004ABF18 /* FetchChatList.swift in Sources */,
|
D0C26D6D1FE286C3004ABF18 /* FetchChatList.swift in Sources */,
|
||||||
D073CE6E1DCBCF17007511FD /* ForwardSourceInfoAttribute.swift in Sources */,
|
D073CE6E1DCBCF17007511FD /* ForwardSourceInfoAttribute.swift in Sources */,
|
||||||
|
D093D7FA20641AA500BC3599 /* SecureIdEmailField.swift in Sources */,
|
||||||
D05A32E21E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift in Sources */,
|
D05A32E21E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift in Sources */,
|
||||||
D0613FD01E60520700202CDB /* ChannelMembers.swift in Sources */,
|
D0613FD01E60520700202CDB /* ChannelMembers.swift in Sources */,
|
||||||
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */,
|
D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */,
|
||||||
@@ -2302,6 +2368,7 @@
|
|||||||
D0B418A91D7E0597004562A4 /* Buffer.swift in Sources */,
|
D0B418A91D7E0597004562A4 /* Buffer.swift in Sources */,
|
||||||
D02ABC821E310E5D00CAE539 /* ManagedCloudChatRemoveMessagesOperations.swift in Sources */,
|
D02ABC821E310E5D00CAE539 /* ManagedCloudChatRemoveMessagesOperations.swift in Sources */,
|
||||||
C2FD33E51E687BF1008D13D4 /* PeerPhotoUpdater.swift in Sources */,
|
C2FD33E51E687BF1008D13D4 /* PeerPhotoUpdater.swift in Sources */,
|
||||||
|
D0BE304C20627D9800FBE6D8 /* AccessSecureId.swift in Sources */,
|
||||||
D0B8442E1DAB91E0005F29E1 /* NBMetadataCoreTestMapper.m in Sources */,
|
D0B8442E1DAB91E0005F29E1 /* NBMetadataCoreTestMapper.m in Sources */,
|
||||||
D01A21AD1F38D10E00DDA104 /* SavedStickerItem.swift in Sources */,
|
D01A21AD1F38D10E00DDA104 /* SavedStickerItem.swift in Sources */,
|
||||||
D03C53731DAD5CA9004C17B3 /* CachedGroupData.swift in Sources */,
|
D03C53731DAD5CA9004C17B3 /* CachedGroupData.swift in Sources */,
|
||||||
@@ -2396,6 +2463,7 @@
|
|||||||
D099D7471EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */,
|
D099D7471EEF0C2700A3128C /* ChannelMessageStateVersionAttribute.swift in Sources */,
|
||||||
D058E0D21E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */,
|
D058E0D21E8AD65C00A442DE /* StandaloneSendMessage.swift in Sources */,
|
||||||
D03C536F1DAD5CA9004C17B3 /* BotInfo.swift in Sources */,
|
D03C536F1DAD5CA9004C17B3 /* BotInfo.swift in Sources */,
|
||||||
|
D093D7EC206413C900BC3599 /* SecureIdPassportIdentity.swift in Sources */,
|
||||||
D0FA8BBA1E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */,
|
D0FA8BBA1E2240B4001E855B /* SecretChatIncomingDecryptedOperation.swift in Sources */,
|
||||||
D033FEB41E61F3C000644997 /* ReportPeer.swift in Sources */,
|
D033FEB41E61F3C000644997 /* ReportPeer.swift in Sources */,
|
||||||
D0FA8BAE1E1FD6E2001E855B /* MemoryBufferExtensions.swift in Sources */,
|
D0FA8BAE1E1FD6E2001E855B /* MemoryBufferExtensions.swift in Sources */,
|
||||||
|
|||||||
185
TelegramCore/AccessSecureId.swift
Normal file
185
TelegramCore/AccessSecureId.swift
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
import Foundation
|
||||||
|
#if os(macOS)
|
||||||
|
import PostboxMac
|
||||||
|
import MtProtoKitMac
|
||||||
|
import SwiftSignalKitMac
|
||||||
|
#else
|
||||||
|
import Postbox
|
||||||
|
import MtProtoKitDynamic
|
||||||
|
import SwiftSignalKit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
import TelegramCorePrivateModule
|
||||||
|
|
||||||
|
private enum GenerateSecureSecretError {
|
||||||
|
case generic
|
||||||
|
}
|
||||||
|
|
||||||
|
func decryptedSecureSecret(encryptedSecretData: Data, password: String) -> Data? {
|
||||||
|
guard let passwordData = password.data(using: .utf8) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
let passwordHash = sha512Digest(passwordData)
|
||||||
|
let secretKey = passwordHash.subdata(in: 0 ..< 32)
|
||||||
|
let iv = passwordHash.subdata(in: 32 ..< (32 + 16))
|
||||||
|
|
||||||
|
var decryptedSecret = Data(count: encryptedSecretData.count)
|
||||||
|
|
||||||
|
guard decryptedSecret.withUnsafeMutableBytes({ (decryptedSecretBytes: UnsafeMutablePointer<Int8>) -> Bool in
|
||||||
|
return secretKey.withUnsafeBytes { (secretKeyBytes: UnsafePointer<Int8>) -> Bool in
|
||||||
|
return iv.withUnsafeBytes { (ivBytes: UnsafePointer<Int8>) -> Bool in
|
||||||
|
return encryptedSecretData.withUnsafeBytes { (encryptedSecretDataBytes: UnsafePointer<Int8>) -> Bool in
|
||||||
|
var processedCount: Int = 0
|
||||||
|
let result = CCCrypt(CCOperation(kCCDecrypt), CCAlgorithm(kCCAlgorithmAES128), 0, secretKeyBytes, secretKey.count, ivBytes, encryptedSecretDataBytes, encryptedSecretData.count, decryptedSecretBytes, decryptedSecret.count, &processedCount)
|
||||||
|
if result != kCCSuccess {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if processedCount != decryptedSecret.count {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
guard decryptedSecret.withUnsafeMutableBytes({ (bytes: UnsafeMutablePointer<UInt8>) -> Bool in
|
||||||
|
var checksum: UInt32 = 0
|
||||||
|
for i in 0 ..< decryptedSecret.count {
|
||||||
|
checksum += UInt32(bytes.advanced(by: i).pointee)
|
||||||
|
checksum = checksum % 255
|
||||||
|
}
|
||||||
|
if checksum == 239 {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return decryptedSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
func encryptedSecureSecret(secretData: Data, password: String) -> Data? {
|
||||||
|
guard let passwordData = password.data(using: .utf8) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let passwordHash = sha512Digest(passwordData)
|
||||||
|
let secretKey = passwordHash.subdata(in: 0 ..< 32)
|
||||||
|
let iv = passwordHash.subdata(in: 32 ..< (32 + 16))
|
||||||
|
|
||||||
|
var encryptedSecret = Data(count: secretData.count)
|
||||||
|
|
||||||
|
guard encryptedSecret.withUnsafeMutableBytes({ (encryptedSecretBytes: UnsafeMutablePointer<Int8>) -> Bool in
|
||||||
|
return secretKey.withUnsafeBytes { (secretKeyBytes: UnsafePointer<Int8>) -> Bool in
|
||||||
|
return iv.withUnsafeBytes { (ivBytes: UnsafePointer<Int8>) -> Bool in
|
||||||
|
return secretData.withUnsafeBytes { (secretDataBytes: UnsafePointer<Int8>) -> Bool in
|
||||||
|
var processedCount: Int = 0
|
||||||
|
let result = CCCrypt(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES128), 0, secretKeyBytes, secretKey.count, ivBytes, secretDataBytes, secretData.count, encryptedSecretBytes, encryptedSecret.count, &processedCount)
|
||||||
|
if result != kCCSuccess {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if processedCount != encryptedSecret.count {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if decryptedSecureSecret(encryptedSecretData: encryptedSecret, password: password) != secretData {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return encryptedSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
private func generateSecureSecret(network: Network, password: String) -> Signal<Data, GenerateSecureSecretError> {
|
||||||
|
var secretData = Data(count: 32)
|
||||||
|
guard secretData.withUnsafeMutableBytes({ (bytes: UnsafeMutablePointer<Int8>) -> Bool in
|
||||||
|
let copyResult = SecRandomCopyBytes(nil, 32, bytes)
|
||||||
|
return copyResult == errSecSuccess
|
||||||
|
}) else {
|
||||||
|
return .fail(.generic)
|
||||||
|
}
|
||||||
|
|
||||||
|
secretData.withUnsafeMutableBytes({ (bytes: UnsafeMutablePointer<UInt8>) in
|
||||||
|
while true {
|
||||||
|
var checksum: UInt32 = 0
|
||||||
|
for i in 0 ..< secretData.count {
|
||||||
|
checksum += UInt32(bytes.advanced(by: i).pointee)
|
||||||
|
checksum = checksum % 255
|
||||||
|
}
|
||||||
|
if checksum == 239 {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
var i = secretData.count - 1
|
||||||
|
inner: while i >= 0 {
|
||||||
|
var byte = bytes.advanced(by: i).pointee
|
||||||
|
if byte != 0xff {
|
||||||
|
byte += 1
|
||||||
|
bytes.advanced(by: i).pointee = byte
|
||||||
|
break inner
|
||||||
|
} else {
|
||||||
|
byte = 0
|
||||||
|
bytes.advanced(by: i).pointee = byte
|
||||||
|
}
|
||||||
|
i -= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
guard let encryptedSecret = encryptedSecureSecret(secretData: secretData, password: password) else {
|
||||||
|
return .fail(.generic)
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateTwoStepVerificationSecureSecret(network: network, password: password, updatedSecret: encryptedSecret)
|
||||||
|
|> mapError { _ -> GenerateSecureSecretError in
|
||||||
|
return .generic
|
||||||
|
}
|
||||||
|
|> map { _ -> Data in
|
||||||
|
return secretData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct SecureIdAccessContext {
|
||||||
|
let secret: Data
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SecureIdAccessError {
|
||||||
|
case generic
|
||||||
|
case passwordError(AuthorizationPasswordVerificationError)
|
||||||
|
case secretPasswordMismatch
|
||||||
|
}
|
||||||
|
|
||||||
|
public func accessSecureId(network: Network, password: String) -> Signal<SecureIdAccessContext, SecureIdAccessError> {
|
||||||
|
return requestTwoStepVerifiationSettings(network: network, password: password)
|
||||||
|
|> mapError { error -> SecureIdAccessError in
|
||||||
|
return .passwordError(error)
|
||||||
|
}
|
||||||
|
|> mapToSignal { settings -> Signal<SecureIdAccessContext, SecureIdAccessError> in
|
||||||
|
if let secureSecret = settings.secureSecret {
|
||||||
|
if let decryptedSecret = decryptedSecureSecret(encryptedSecretData: secureSecret, password: "q") { //password
|
||||||
|
return .single(SecureIdAccessContext(secret: decryptedSecret))
|
||||||
|
} else {
|
||||||
|
return .fail(.secretPasswordMismatch)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return generateSecureSecret(network: network, password: password)
|
||||||
|
|> mapError { _ -> SecureIdAccessError in
|
||||||
|
return SecureIdAccessError.generic
|
||||||
|
}
|
||||||
|
|> map { decryptedSecret in
|
||||||
|
return SecureIdAccessContext(secret: decryptedSecret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -336,12 +336,12 @@ public func accountWithId(networkArguments: NetworkInitializationArguments, id:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct TwoStepAuthData {
|
public struct TwoStepAuthData {
|
||||||
let nextSalt: Data
|
public let nextSalt: Data
|
||||||
let currentSalt: Data?
|
public let currentSalt: Data?
|
||||||
let hasRecovery: Bool
|
public let hasRecovery: Bool
|
||||||
let currentHint: String?
|
public let currentHint: String?
|
||||||
let unconfirmedEmailPattern: String?
|
public let unconfirmedEmailPattern: String?
|
||||||
let secretRandom: Data
|
public let secretRandom: Data
|
||||||
}
|
}
|
||||||
|
|
||||||
public func twoStepAuthData(_ network: Network) -> Signal<TwoStepAuthData, MTRpcError> {
|
public func twoStepAuthData(_ network: Network) -> Signal<TwoStepAuthData, MTRpcError> {
|
||||||
@@ -378,6 +378,17 @@ func sha256Digest(_ data : Data) -> Data {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sha512Digest(_ data : Data) -> Data {
|
||||||
|
var res = Data()
|
||||||
|
res.count = Int(CC_SHA512_DIGEST_LENGTH)
|
||||||
|
res.withUnsafeMutableBytes { mutableBytes -> Void in
|
||||||
|
data.withUnsafeBytes { bytes -> Void in
|
||||||
|
CC_SHA512(bytes, CC_LONG(data.count), mutableBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
public func verifyPassword(_ account: UnauthorizedAccount, password: String) -> Signal<Api.auth.Authorization, MTRpcError> {
|
public func verifyPassword(_ account: UnauthorizedAccount, password: String) -> Signal<Api.auth.Authorization, MTRpcError> {
|
||||||
return twoStepAuthData(account.network)
|
return twoStepAuthData(account.network)
|
||||||
|> mapToSignal { authData -> Signal<Api.auth.Authorization, MTRpcError> in
|
|> mapToSignal { authData -> Signal<Api.auth.Authorization, MTRpcError> in
|
||||||
|
|||||||
@@ -13,7 +13,14 @@ public enum RequestSecureIdFormError {
|
|||||||
case generic
|
case generic
|
||||||
}
|
}
|
||||||
|
|
||||||
private func parseFieldType(_ type: Api.AuthFieldType) -> SecureIdFieldType {
|
public enum RequestedSecureIdField {
|
||||||
|
case identity
|
||||||
|
case address
|
||||||
|
case phone
|
||||||
|
case email
|
||||||
|
}
|
||||||
|
|
||||||
|
private func parseRequestedFieldType(_ type: Api.AuthFieldType) -> RequestedSecureIdField {
|
||||||
switch type {
|
switch type {
|
||||||
case .authFieldTypeIdentity:
|
case .authFieldTypeIdentity:
|
||||||
return .identity
|
return .identity
|
||||||
@@ -35,7 +42,7 @@ private func parseFileReference(_ file: Api.SecureFile) -> SecureIdFileReference
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func parseValue(_ value: Api.SecureValue) -> SecureIdFieldValue {
|
/*private func parseValue(_ value: Api.SecureValue) -> SecureIdFieldValue {
|
||||||
switch value {
|
switch value {
|
||||||
case let .secureValueEmpty(name):
|
case let .secureValueEmpty(name):
|
||||||
return SecureIdFieldValue(name: name, data: .none)
|
return SecureIdFieldValue(name: name, data: .none)
|
||||||
@@ -46,16 +53,75 @@ private func parseValue(_ value: Api.SecureValue) -> SecureIdFieldValue {
|
|||||||
case let .secureValueText(name, text, hash):
|
case let .secureValueText(name, text, hash):
|
||||||
return SecureIdFieldValue(name: name, data: .text(text: text, hash: hash))
|
return SecureIdFieldValue(name: name, data: .text(text: text, hash: hash))
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
private func parseIdentityField(context: SecureIdAccessContext, value: Api.SecureValue, document: Api.SecureValue?) -> SecureIdIdentityField? {
|
||||||
|
switch value {
|
||||||
|
case let .secureValueData(name, data, hash, secret):
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func parseField(_ field: Api.AuthField) -> SecureIdField {
|
private func parsePhoneField(context: SecureIdAccessContext, value: Api.SecureValue) -> SecureIdPhoneField? {
|
||||||
|
switch value {
|
||||||
|
case let .secureValueText(name, text, _):
|
||||||
|
return SecureIdPhoneField(rawValue: text)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func parseEmailField(context: SecureIdAccessContext, value: Api.SecureValue) -> SecureIdEmailField? {
|
||||||
|
switch value {
|
||||||
|
case let .secureValueText(name, text, _):
|
||||||
|
return SecureIdEmailField(rawValue: text)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func parseFields(context: SecureIdAccessContext, fields: [Api.AuthField]) -> SecureIdFields {
|
||||||
|
var result = SecureIdFields(identity: nil, phone: nil, email: nil)
|
||||||
|
for field in fields {
|
||||||
switch field {
|
switch field {
|
||||||
case let .authField(_, type, data, document):
|
case let .authField(_, type, data, document):
|
||||||
return SecureIdField(type: parseFieldType(type), value: parseValue(data))
|
switch type {
|
||||||
|
case .authFieldTypeIdentity:
|
||||||
|
if let identity = parseIdentityField(context: context, value: data, document: document) {
|
||||||
|
result.identity = .value(identity)
|
||||||
|
} else {
|
||||||
|
result.identity = .empty
|
||||||
}
|
}
|
||||||
|
case .authFieldTypeAddress:
|
||||||
|
break
|
||||||
|
case .authFieldTypePhone:
|
||||||
|
if let phone = parsePhoneField(context: context, value: data) {
|
||||||
|
result.phone = .value(phone)
|
||||||
|
} else {
|
||||||
|
result.phone = .empty
|
||||||
|
}
|
||||||
|
case .authFieldTypeEmail:
|
||||||
|
if let email = parseEmailField(context: context, value: data) {
|
||||||
|
result.email = .value(email)
|
||||||
|
} else {
|
||||||
|
result.email = .empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: PeerId, scope: [String], origin: String?, packageName: String?, bundleId: String?, publicKey: String?) -> Signal<SecureIdForm, RequestSecureIdFormError> {
|
public struct EncryptedSecureIdForm {
|
||||||
|
public let peerId: PeerId
|
||||||
|
public let requestedFields: [RequestedSecureIdField]
|
||||||
|
|
||||||
|
let encryptedFields: [Api.AuthField]
|
||||||
|
}
|
||||||
|
|
||||||
|
public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: PeerId, scope: [String], origin: String?, packageName: String?, bundleId: String?, publicKey: String?) -> Signal<EncryptedSecureIdForm, RequestSecureIdFormError> {
|
||||||
if peerId.namespace != Namespaces.Peer.CloudUser {
|
if peerId.namespace != Namespaces.Peer.CloudUser {
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
@@ -76,10 +142,10 @@ public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: Peer
|
|||||||
|> mapError { _ -> RequestSecureIdFormError in
|
|> mapError { _ -> RequestSecureIdFormError in
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { result -> Signal<SecureIdForm, RequestSecureIdFormError> in
|
|> mapToSignal { result -> Signal<EncryptedSecureIdForm, RequestSecureIdFormError> in
|
||||||
return postbox.modify { modifier -> SecureIdForm in
|
return postbox.modify { modifier -> EncryptedSecureIdForm in
|
||||||
switch result {
|
switch result {
|
||||||
case let .authorizationForm(_, botId, fields, acceptedFields, users):
|
case let .authorizationForm(_, botId, fields, _, users):
|
||||||
var peers: [Peer] = []
|
var peers: [Peer] = []
|
||||||
for user in users {
|
for user in users {
|
||||||
let parsed = TelegramUser(user: user)
|
let parsed = TelegramUser(user: user)
|
||||||
@@ -89,10 +155,17 @@ public func requestSecureIdForm(postbox: Postbox, network: Network, peerId: Peer
|
|||||||
return updated
|
return updated
|
||||||
})
|
})
|
||||||
|
|
||||||
let parsedFields = fields.map(parseField)
|
return EncryptedSecureIdForm(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: botId), requestedFields: fields.map { field -> RequestedSecureIdField in
|
||||||
|
switch field {
|
||||||
return SecureIdForm(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: botId), fields: parsedFields)
|
case let .authField(_, type, data, document):
|
||||||
|
return parseRequestedFieldType(type)
|
||||||
|
}
|
||||||
|
}, encryptedFields: fields)
|
||||||
}
|
}
|
||||||
} |> mapError { _ in return RequestSecureIdFormError.generic }
|
} |> mapError { _ in return RequestSecureIdFormError.generic }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func decryptedSecureIdForm(context: SecureIdAccessContext, form: EncryptedSecureIdForm) -> SecureIdForm? {
|
||||||
|
return SecureIdForm(peerId: form.peerId, fields: parseFields(context: context, fields: form.encryptedFields))
|
||||||
|
}
|
||||||
|
|||||||
43
TelegramCore/SecureIdDataTypes.swift
Normal file
43
TelegramCore/SecureIdDataTypes.swift
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct SecureIdDate: Equatable {
|
||||||
|
private var timestamp: Int32
|
||||||
|
|
||||||
|
public init(timestamp: Int32) {
|
||||||
|
self.timestamp = timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: SecureIdDate, rhs: SecureIdDate) -> Bool {
|
||||||
|
if lhs.timestamp != rhs.timestamp {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SecureIdGender {
|
||||||
|
case male
|
||||||
|
case female
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum SecureIdFileReference: Equatable {
|
||||||
|
case none
|
||||||
|
case file(id: Int64, accessHash: Int64, size: Int32, datacenterId: Int32, fileHash: String)
|
||||||
|
|
||||||
|
public static func ==(lhs: SecureIdFileReference, rhs: SecureIdFileReference) -> Bool {
|
||||||
|
switch lhs {
|
||||||
|
case .none:
|
||||||
|
if case .none = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .file(id, accessHash, size, datacenterId, fileHash):
|
||||||
|
if case .file(id, accessHash, size, datacenterId, fileHash) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
TelegramCore/SecureIdEmailField.swift
Normal file
16
TelegramCore/SecureIdEmailField.swift
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct SecureIdEmailField: Equatable {
|
||||||
|
public let rawValue: String
|
||||||
|
|
||||||
|
public init(rawValue: String) {
|
||||||
|
self.rawValue = rawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: SecureIdEmailField, rhs: SecureIdEmailField) -> Bool {
|
||||||
|
if lhs.rawValue != rhs.rawValue {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,36 +5,77 @@ import Foundation
|
|||||||
import Postbox
|
import Postbox
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public enum SecureIdFieldType {
|
public enum SecureIdFieldValue<T>: Equatable where T: Equatable {
|
||||||
case identity
|
case empty
|
||||||
case address
|
case value(T)
|
||||||
case phone
|
|
||||||
case email
|
public static func ==(lhs: SecureIdFieldValue<T>, rhs: SecureIdFieldValue<T>) -> Bool {
|
||||||
|
switch lhs {
|
||||||
|
case .empty:
|
||||||
|
if case .empty = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .value(value):
|
||||||
|
if case .value(value) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SecureIdFileReference {
|
public struct SecureIdFields: Equatable {
|
||||||
case none
|
public var identity: SecureIdFieldValue<SecureIdIdentityField>?
|
||||||
case file(id: Int64, accessHash: Int64, size: Int32, datacenterId: Int32, fileHash: String)
|
public var phone: SecureIdFieldValue<SecureIdPhoneField>?
|
||||||
|
public var email: SecureIdFieldValue<SecureIdEmailField>?
|
||||||
|
|
||||||
|
public static func ==(lhs: SecureIdFields, rhs: SecureIdFields) -> Bool {
|
||||||
|
if lhs.identity != rhs.identity {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.phone != rhs.phone {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.email != rhs.email {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SecureIdFieldValueData {
|
public enum SecureIdField: Equatable {
|
||||||
case none
|
case identity(SecureIdIdentityField)
|
||||||
case data(data: Data, hash: String, secret: Data)
|
case phone(SecureIdPhoneField)
|
||||||
case files(files: [SecureIdFileReference], hash: String, secret: Data)
|
case email(SecureIdEmailField)
|
||||||
case text(text: String, hash: String)
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct SecureIdFieldValue {
|
public static func ==(lhs: SecureIdField, rhs: SecureIdField) -> Bool {
|
||||||
public let name: String
|
switch lhs {
|
||||||
public let data: SecureIdFieldValueData
|
case let .identity(field):
|
||||||
|
if case .identity(field) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .phone(field):
|
||||||
|
if case .phone(field) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .email(field):
|
||||||
|
if case .email(field) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct SecureIdField {
|
|
||||||
public let type: SecureIdFieldType
|
|
||||||
public let value: SecureIdFieldValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct SecureIdForm {
|
public struct SecureIdForm {
|
||||||
public let peerId: PeerId
|
public let peerId: PeerId
|
||||||
public let fields: [SecureIdField]
|
public let fields: SecureIdFields
|
||||||
}
|
}
|
||||||
|
|||||||
16
TelegramCore/SecureIdIdentityField.swift
Normal file
16
TelegramCore/SecureIdIdentityField.swift
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct SecureIdIdentityField: Equatable {
|
||||||
|
public var passport: SecureIdPassportIdentity?
|
||||||
|
|
||||||
|
public init(passport: SecureIdPassportIdentity?) {
|
||||||
|
self.passport = passport
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: SecureIdIdentityField, rhs: SecureIdIdentityField) -> Bool {
|
||||||
|
if lhs.passport != rhs.passport {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
41
TelegramCore/SecureIdPassportIdentity.swift
Normal file
41
TelegramCore/SecureIdPassportIdentity.swift
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct SecureIdPassportIdentity: Equatable {
|
||||||
|
public var id: String
|
||||||
|
public var firstName: String
|
||||||
|
public var lastName: String
|
||||||
|
public var birthdate: SecureIdDate
|
||||||
|
public var countryCode: String
|
||||||
|
public var gender: SecureIdGender
|
||||||
|
|
||||||
|
public init(id: String, firstName: String, lastName: String, birthdate: SecureIdDate, countryCode: String, gender: SecureIdGender) {
|
||||||
|
self.id = id
|
||||||
|
self.firstName = firstName
|
||||||
|
self.lastName = lastName
|
||||||
|
self.birthdate = birthdate
|
||||||
|
self.countryCode = countryCode
|
||||||
|
self.gender = gender
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: SecureIdPassportIdentity, rhs: SecureIdPassportIdentity) -> Bool {
|
||||||
|
if lhs.id != rhs.id {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.firstName != rhs.firstName {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.lastName != rhs.lastName {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.birthdate != rhs.birthdate {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.countryCode != rhs.countryCode {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.gender != rhs.gender {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
16
TelegramCore/SecureIdPhoneField.swift
Normal file
16
TelegramCore/SecureIdPhoneField.swift
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct SecureIdPhoneField: Equatable {
|
||||||
|
public let rawValue: String
|
||||||
|
|
||||||
|
public init(rawValue: String) {
|
||||||
|
self.rawValue = rawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: SecureIdPhoneField, rhs: SecureIdPhoneField) -> Bool {
|
||||||
|
if lhs.rawValue != rhs.rawValue {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,10 +29,11 @@ public func twoStepVerificationConfiguration(account: Account) -> Signal<TwoStep
|
|||||||
|
|
||||||
public struct TwoStepVerificationSettings {
|
public struct TwoStepVerificationSettings {
|
||||||
public let email: String
|
public let email: String
|
||||||
|
public let secureSecret: Data?
|
||||||
}
|
}
|
||||||
|
|
||||||
public func requestTwoStepVerifiationSettings(account: Account, password: String) -> Signal<TwoStepVerificationSettings, AuthorizationPasswordVerificationError> {
|
public func requestTwoStepVerifiationSettings(network: Network, password: String) -> Signal<TwoStepVerificationSettings, AuthorizationPasswordVerificationError> {
|
||||||
return twoStepAuthData(account.network)
|
return twoStepAuthData(network)
|
||||||
|> mapToSignal { authData -> Signal<TwoStepVerificationSettings, MTRpcError> in
|
|> mapToSignal { authData -> Signal<TwoStepVerificationSettings, MTRpcError> in
|
||||||
var data = Data()
|
var data = Data()
|
||||||
data.append(authData.currentSalt!)
|
data.append(authData.currentSalt!)
|
||||||
@@ -40,11 +41,11 @@ public func requestTwoStepVerifiationSettings(account: Account, password: String
|
|||||||
data.append(authData.currentSalt!)
|
data.append(authData.currentSalt!)
|
||||||
let currentPasswordHash = sha256Digest(data)
|
let currentPasswordHash = sha256Digest(data)
|
||||||
|
|
||||||
return account.network.request(Api.functions.account.getPasswordSettings(currentPasswordHash: Buffer(data: currentPasswordHash)), automaticFloodWait: false)
|
return network.request(Api.functions.account.getPasswordSettings(currentPasswordHash: Buffer(data: currentPasswordHash)), automaticFloodWait: false)
|
||||||
|> map { result -> TwoStepVerificationSettings in
|
|> map { result -> TwoStepVerificationSettings in
|
||||||
switch result {
|
switch result {
|
||||||
case let .passwordSettings(email, _):
|
case let .passwordSettings(email, secureSecret):
|
||||||
return TwoStepVerificationSettings(email: email)
|
return TwoStepVerificationSettings(email: email, secureSecret: secureSecret.size == 0 ? nil : secureSecret.makeData())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,12 +75,25 @@ public enum UpdatedTwoStepVerificationPassword {
|
|||||||
case password(password: String, hint: String, email: String?)
|
case password(password: String, hint: String, email: String?)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateTwoStepVerificationPassword(account: Account, currentPassword: String?, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
|
public func updateTwoStepVerificationPassword(network: Network, currentPassword: String?, updatedPassword: UpdatedTwoStepVerificationPassword) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
|
||||||
return twoStepAuthData(account.network)
|
return twoStepAuthData(network)
|
||||||
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { authData -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> in
|
|> mapToSignal { authData -> Signal<(TwoStepAuthData, Data?), UpdateTwoStepVerificationPasswordError> in
|
||||||
|
if authData.currentSalt != nil {
|
||||||
|
return requestTwoStepVerifiationSettings(network: network, password: currentPassword ?? "")
|
||||||
|
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
||||||
|
return .generic
|
||||||
|
}
|
||||||
|
|> map { settings in
|
||||||
|
return (authData, settings.secureSecret)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return .single((authData, nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> mapToSignal { authData, secureSecret -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> in
|
||||||
let currentPasswordHash: Buffer
|
let currentPasswordHash: Buffer
|
||||||
if let currentSalt = authData.currentSalt {
|
if let currentSalt = authData.currentSalt {
|
||||||
var data = Data()
|
var data = Data()
|
||||||
@@ -100,7 +114,7 @@ public func updateTwoStepVerificationPassword(account: Account, currentPassword:
|
|||||||
flags |= (1 << 0)
|
flags |= (1 << 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return account.network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: .passwordInputSettings(flags: flags, newSalt: Buffer(data: Data()), newPasswordHash: Buffer(data: Data()), hint: "", email: "", newSecureSecret: nil)), automaticFloodWait: false)
|
return network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: .passwordInputSettings(flags: flags, newSalt: Buffer(data: Data()), newPasswordHash: Buffer(data: Data()), hint: "", email: "", newSecureSecret: nil)), automaticFloodWait: false)
|
||||||
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
@@ -126,14 +140,24 @@ public func updateTwoStepVerificationPassword(account: Account, currentPassword:
|
|||||||
updatedData.append(password.data(using: .utf8, allowLossyConversion: true)!)
|
updatedData.append(password.data(using: .utf8, allowLossyConversion: true)!)
|
||||||
updatedData.append(nextSalt)
|
updatedData.append(nextSalt)
|
||||||
|
|
||||||
|
var updatedSecureSecret: Data?
|
||||||
|
if let encryptedSecret = secureSecret {
|
||||||
|
flags |= 1 << 2
|
||||||
|
if let decryptedSecret = decryptedSecureSecret(encryptedSecretData: encryptedSecret, password: currentPassword ?? "") {
|
||||||
|
updatedSecureSecret = encryptedSecureSecret(secretData: decryptedSecret, password: password)
|
||||||
|
} else {
|
||||||
|
updatedSecureSecret = Data()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let updatedPasswordHash = sha256Digest(updatedData)
|
let updatedPasswordHash = sha256Digest(updatedData)
|
||||||
return account.network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: Api.account.PasswordInputSettings.passwordInputSettings(flags: flags, newSalt: Buffer(data: nextSalt), newPasswordHash: Buffer(data: updatedPasswordHash), hint: hint, email: email, newSecureSecret: nil)), automaticFloodWait: false)
|
return network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: Api.account.PasswordInputSettings.passwordInputSettings(flags: flags, newSalt: Buffer(data: nextSalt), newPasswordHash: Buffer(data: updatedPasswordHash), hint: hint, email: email, newSecureSecret: updatedSecureSecret.flatMap(Buffer.init))), automaticFloodWait: false)
|
||||||
|> map { _ -> UpdateTwoStepVerificationPasswordResult in
|
|> map { _ -> UpdateTwoStepVerificationPasswordResult in
|
||||||
return .password(password: password, pendingEmailPattern: nil)
|
return .password(password: password, pendingEmailPattern: nil)
|
||||||
}
|
}
|
||||||
|> `catch` { error -> Signal<UpdateTwoStepVerificationPasswordResult, MTRpcError> in
|
|> `catch` { error -> Signal<UpdateTwoStepVerificationPasswordResult, MTRpcError> in
|
||||||
if error.errorDescription == "EMAIL_UNCONFIRMED" {
|
if error.errorDescription == "EMAIL_UNCONFIRMED" {
|
||||||
return twoStepAuthData(account.network)
|
return twoStepAuthData(network)
|
||||||
|> map { result -> UpdateTwoStepVerificationPasswordResult in
|
|> map { result -> UpdateTwoStepVerificationPasswordResult in
|
||||||
return .password(password: password, pendingEmailPattern: result.unconfirmedEmailPattern)
|
return .password(password: password, pendingEmailPattern: result.unconfirmedEmailPattern)
|
||||||
}
|
}
|
||||||
@@ -152,6 +176,41 @@ public func updateTwoStepVerificationPassword(account: Account, currentPassword:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum UpdateTwoStepVerificationSecureSecretResult {
|
||||||
|
case success
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UpdateTwoStepVerificationSecureSecretError {
|
||||||
|
case generic
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateTwoStepVerificationSecureSecret(network: Network, password: String, updatedSecret: Data) -> Signal<UpdateTwoStepVerificationSecureSecretResult, UpdateTwoStepVerificationSecureSecretError> {
|
||||||
|
return twoStepAuthData(network)
|
||||||
|
|> mapError { _ -> UpdateTwoStepVerificationSecureSecretError in
|
||||||
|
return .generic
|
||||||
|
}
|
||||||
|
|> mapToSignal { authData -> Signal<UpdateTwoStepVerificationSecureSecretResult, UpdateTwoStepVerificationSecureSecretError> in
|
||||||
|
guard let currentSalt = authData.currentSalt else {
|
||||||
|
return .fail(.generic)
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = Data()
|
||||||
|
data.append(currentSalt)
|
||||||
|
data.append(password.data(using: .utf8, allowLossyConversion: true)!)
|
||||||
|
data.append(currentSalt)
|
||||||
|
let currentPasswordHash = Buffer(data: sha256Digest(data))
|
||||||
|
|
||||||
|
let flags: Int32 = (1 << 2)
|
||||||
|
return network.request(Api.functions.account.updatePasswordSettings(currentPasswordHash: currentPasswordHash, newSettings: .passwordInputSettings(flags: flags, newSalt: nil, newPasswordHash: nil, hint: nil, email: nil, newSecureSecret: Buffer(data: updatedSecret))), automaticFloodWait: false)
|
||||||
|
|> mapError { _ -> UpdateTwoStepVerificationSecureSecretError in
|
||||||
|
return .generic
|
||||||
|
}
|
||||||
|
|> map { _ -> UpdateTwoStepVerificationSecureSecretResult in
|
||||||
|
return .success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func updateTwoStepVerificationEmail(account: Account, currentPassword: String, updatedEmail: String) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
|
public func updateTwoStepVerificationEmail(account: Account, currentPassword: String, updatedEmail: String) -> Signal<UpdateTwoStepVerificationPasswordResult, UpdateTwoStepVerificationPasswordError> {
|
||||||
return twoStepAuthData(account.network)
|
return twoStepAuthData(account.network)
|
||||||
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
|> mapError { _ -> UpdateTwoStepVerificationPasswordError in
|
||||||
|
|||||||
Reference in New Issue
Block a user