Fix open group message deletion

This commit is contained in:
Niels Andriesse 2021-01-21 11:27:52 +11:00
parent d873b56fd4
commit 3e5baca72d
7 changed files with 34 additions and 20 deletions

View File

@ -1162,25 +1162,23 @@ NSString *NSStringForOWSMessageCellType(OWSMessageCellType cellType)
- (BOOL)userCanDeleteGroupMessage
{
if (!self.isGroupThread) return false;
// Ensure the thread is a public chat and not an RSS feed
TSGroupThread *groupThread = (TSGroupThread *)self.interaction.thread;
// Only allow deletion on incoming and outgoing messages
OWSInteractionType interationType = self.interaction.interactionType;
if (interationType != OWSInteractionType_OutgoingMessage && interationType != OWSInteractionType_IncomingMessage) return false;
// Make sure it's a public chat message
// Make sure it's an open group message
TSMessage *message = (TSMessage *)self.interaction;
if (!message.isOpenGroupMessage) return true;
// Ensure we have the details needed to contact the server
SNOpenGroup *publicChat = [LKStorage.shared getOpenGroupForThreadID:groupThread.uniqueId];
if (publicChat == nil) return true;
SNOpenGroup *openGroup = [LKStorage.shared getOpenGroupForThreadID:groupThread.uniqueId];
if (openGroup == nil) return true;
if (interationType == OWSInteractionType_IncomingMessage) {
// Only allow deletion on incoming messages if the user has moderation permission
return [SNOpenGroupAPI isUserModerator:[SNGeneralUtilities getUserPublicKey] forChannel:publicChat.channel onServer:publicChat.server];
return [SNOpenGroupAPI isUserModerator:[SNGeneralUtilities getUserPublicKey] forChannel:openGroup.channel onServer:openGroup.server];
} else {
return YES;
}

View File

@ -190,14 +190,18 @@ extension Storage {
(transaction as! YapDatabaseReadWriteTransaction).setObject(newValue, forKey: openGroupID, inCollection: Storage.openGroupUserCountCollection)
}
public func getIDForMessage(withServerID serverID: UInt64) -> UInt64? {
var result: UInt64? = nil
public func getIDForMessage(withServerID serverID: UInt64) -> String? {
var result: String? = nil
Storage.read { transaction in
result = transaction.object(forKey: String(serverID), inCollection: Storage.openGroupMessageIDCollection) as? UInt64
result = transaction.object(forKey: String(serverID), inCollection: Storage.openGroupMessageIDCollection) as? String
}
return result
}
public func setIDForMessage(withServerID serverID: UInt64, to messageID: String, using transaction: Any) {
(transaction as! YapDatabaseReadWriteTransaction).setObject(messageID, forKey: String(serverID), inCollection: Storage.openGroupMessageIDCollection)
}
public func setOpenGroupDisplayName(to displayName: String, for publicKey: String, inOpenGroupWithID openGroupID: String, using transaction: Any) {
let collection = openGroupID
(transaction as! YapDatabaseReadWriteTransaction).setObject(displayName, forKey: publicKey, inCollection: collection)

View File

@ -205,7 +205,7 @@ public final class OpenGroupAPI : DotNetAPI {
}
let lastDeletionServerID = storage.getLastDeletionServerID(for: channel, on: server)
if serverID > (lastDeletionServerID ?? 0) {
storage.writeSync { transaction in
storage.write { transaction in
storage.setLastDeletionServerID(for: channel, on: server, to: serverID, using: transaction)
}
}
@ -218,13 +218,13 @@ public final class OpenGroupAPI : DotNetAPI {
@objc(deleteMessageWithID:forGroup:onServer:isSentByUser:)
public static func objc_deleteMessage(with messageID: UInt, for group: UInt64, on server: String, isSentByUser: Bool) -> AnyPromise {
return AnyPromise.from(deleteMessage(with: messageID, for: group, on: server, isSentByUser: isSentByUser))
return AnyPromise.from(deleteMessage(with: messageID, for: group, on: server, wasSentByUser: isSentByUser))
}
public static func deleteMessage(with messageID: UInt, for channel: UInt64, on server: String, isSentByUser: Bool) -> Promise<Void> {
let isModerationRequest = !isSentByUser
public static func deleteMessage(with messageID: UInt, for channel: UInt64, on server: String, wasSentByUser: Bool) -> Promise<Void> {
let isModerationRequest = !wasSentByUser
SNLog("Deleting message with ID: \(messageID) for open group channel with ID: \(channel) on server: \(server) (isModerationRequest = \(isModerationRequest)).")
let urlAsString = isSentByUser ? "\(server)/channels/\(channel)/messages/\(messageID)" : "\(server)/loki/v1/moderation/message/\(messageID)"
let urlAsString = wasSentByUser ? "\(server)/channels/\(channel)/messages/\(messageID)" : "\(server)/loki/v1/moderation/message/\(messageID)"
return attempt(maxRetryCount: maxRetryCount, recoveringOn: DispatchQueue.global(qos: .default)) {
getOpenGroupServerPublicKey(for: server).then(on: DispatchQueue.global(qos: .default)) { serverPublicKey in
getAuthToken(for: server).then(on: DispatchQueue.global(qos: .default)) { token -> Promise<Void> in

View File

@ -215,6 +215,10 @@ extension MessageReceiver {
if isMainAppAndActive {
cancelTypingIndicatorsIfNeeded(for: message.sender!)
}
// Keep track of the open group server message ID message ID relationship
if let serverID = message.openGroupServerMessageID {
storage.setIDForMessage(withServerID: serverID, to: tsIncomingMessageID, using: transaction)
}
// Notify the user if needed
guard (isMainAppAndActive || isBackgroundPoll), let tsIncomingMessage = TSIncomingMessage.fetch(uniqueId: tsIncomingMessageID, transaction: transaction),
let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) else { return tsIncomingMessageID }

View File

@ -342,15 +342,21 @@ public final class MessageSender : NSObject {
public static func handleSuccessfulMessageSend(_ message: Message, to destination: Message.Destination, using transaction: Any) {
guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { return }
tsMessage.openGroupServerMessageID = message.openGroupServerMessageID ?? 0
let storage = SNMessagingKitConfiguration.shared.storage
let transaction = transaction as! YapDatabaseReadWriteTransaction
tsMessage.save(with: transaction)
if let serverID = message.openGroupServerMessageID {
storage.setIDForMessage(withServerID: serverID, to: tsMessage.uniqueId!, using: transaction)
}
var recipients = [ message.recipient! ]
if case .closedGroup(_) = destination, let threadID = message.threadID, // threadID should always be set at this point
let thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction as! YapDatabaseReadTransaction), thread.isClosedGroup {
let thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction), thread.isClosedGroup {
recipients = thread.groupModel.groupMemberIds
}
recipients.forEach { recipient in
tsMessage.update(withSentRecipient: recipient, wasSentByUD: true, transaction: transaction as! YapDatabaseReadWriteTransaction)
tsMessage.update(withSentRecipient: recipient, wasSentByUD: true, transaction: transaction)
}
OWSDisappearingMessagesJob.shared().startAnyExpiration(for: tsMessage, expirationStartedAt: NSDate.millisecondTimestamp(), transaction: transaction as! YapDatabaseReadWriteTransaction)
OWSDisappearingMessagesJob.shared().startAnyExpiration(for: tsMessage, expirationStartedAt: NSDate.millisecondTimestamp(), transaction: transaction)
}
public static func handleFailedMessageSend(_ message: Message, with error: Swift.Error, using transaction: Any) {

View File

@ -193,9 +193,10 @@ public final class OpenGroupPoller : NSObject {
let openGroup = self.openGroup
let _ = OpenGroupAPI.getDeletedMessageServerIDs(for: openGroup.channel, on: openGroup.server).done(on: DispatchQueue.global(qos: .default)) { deletedMessageServerIDs in
let deletedMessageIDs = deletedMessageServerIDs.compactMap { Storage.shared.getIDForMessage(withServerID: UInt64($0)) }
SNMessagingKitConfiguration.shared.storage.writeSync { transaction in
SNMessagingKitConfiguration.shared.storage.write { transaction in
deletedMessageIDs.forEach { messageID in
TSMessage.fetch(uniqueId: String(messageID))?.remove(with: transaction as! YapDatabaseReadWriteTransaction)
let transaction = transaction as! YapDatabaseReadWriteTransaction
TSMessage.fetch(uniqueId: messageID, transaction: transaction)?.remove(with: transaction)
}
}
}

View File

@ -71,7 +71,8 @@ public protocol SessionMessagingKitStorageProtocol {
// MARK: - Open Group Metadata
func setUserCount(to newValue: Int, forOpenGroupWithID openGroupID: String, using transaction: Any)
func getIDForMessage(withServerID serverID: UInt64) -> UInt64?
func getIDForMessage(withServerID serverID: UInt64) -> String?
func setIDForMessage(withServerID serverID: UInt64, to messageID: String, using transaction: Any)
func setOpenGroupDisplayName(to displayName: String, for publicKey: String, inOpenGroupWithID openGroupID: String, using transaction: Any)
func setLastProfilePictureUploadDate(_ date: Date) // Stored in user defaults so no transaction is needed