feat: disable typing and message requests in open groups if you don’t have "write" permission

This commit is contained in:
Ryan Zhao 2022-09-15 15:50:15 +10:00
parent 570883e28a
commit 30e0e40ffa
8 changed files with 81 additions and 10 deletions

View File

@ -158,6 +158,7 @@
7BA68909272A27BE00EFC32F /* SessionCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA68908272A27BE00EFC32F /* SessionCall.swift */; };
7BA6890D27325CCC00EFC32F /* SessionCallManager+CXCallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA6890C27325CCC00EFC32F /* SessionCallManager+CXCallController.swift */; };
7BA6890F27325CE300EFC32F /* SessionCallManager+CXProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA6890E27325CE300EFC32F /* SessionCallManager+CXProvider.swift */; };
7BAA7B6628D2DE4700AE1489 /* _009_OpenGroupPermission.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAA7B6528D2DE4700AE1489 /* _009_OpenGroupPermission.swift */; };
7BAADFCC27B0EF23007BCF92 /* CallVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAADFCB27B0EF23007BCF92 /* CallVideoView.swift */; };
7BAADFCE27B215FE007BCF92 /* UIView+Draggable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAADFCD27B215FE007BCF92 /* UIView+Draggable.swift */; };
7BAF54CF27ACCEEC003D12F8 /* GlobalSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF54CC27ACCEEC003D12F8 /* GlobalSearchViewController.swift */; };
@ -166,8 +167,8 @@
7BAF54D427ACCF01003D12F8 /* SAEScreenLockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF54D227ACCF01003D12F8 /* SAEScreenLockViewController.swift */; };
7BAF54D827ACD0E3003D12F8 /* ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF54D527ACD0E2003D12F8 /* ReusableView.swift */; };
7BAF54DC27ACD12B003D12F8 /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF54DB27ACD12B003D12F8 /* UIColor+Extensions.swift */; };
7BBBDC462875600700747E59 /* DocumentTitleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBBDC452875600700747E59 /* DocumentTitleViewController.swift */; };
7BBBDC44286EAD2D00747E59 /* TappableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBBDC43286EAD2D00747E59 /* TappableLabel.swift */; };
7BBBDC462875600700747E59 /* DocumentTitleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBBDC452875600700747E59 /* DocumentTitleViewController.swift */; };
7BC01A3E241F40AB00BC7C55 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */; };
7BC01A42241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
7BC707F227290ACB002817AD /* SessionCallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC707F127290ACB002817AD /* SessionCallManager.swift */; };
@ -1203,6 +1204,7 @@
7BA68908272A27BE00EFC32F /* SessionCall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionCall.swift; sourceTree = "<group>"; };
7BA6890C27325CCC00EFC32F /* SessionCallManager+CXCallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionCallManager+CXCallController.swift"; sourceTree = "<group>"; };
7BA6890E27325CE300EFC32F /* SessionCallManager+CXProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionCallManager+CXProvider.swift"; sourceTree = "<group>"; };
7BAA7B6528D2DE4700AE1489 /* _009_OpenGroupPermission.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _009_OpenGroupPermission.swift; sourceTree = "<group>"; };
7BAADFCB27B0EF23007BCF92 /* CallVideoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallVideoView.swift; sourceTree = "<group>"; };
7BAADFCD27B215FE007BCF92 /* UIView+Draggable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Draggable.swift"; sourceTree = "<group>"; };
7BAF54CC27ACCEEC003D12F8 /* GlobalSearchViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlobalSearchViewController.swift; sourceTree = "<group>"; };
@ -1211,8 +1213,8 @@
7BAF54D227ACCF01003D12F8 /* SAEScreenLockViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SAEScreenLockViewController.swift; sourceTree = "<group>"; };
7BAF54D527ACD0E2003D12F8 /* ReusableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReusableView.swift; sourceTree = "<group>"; };
7BAF54DB27ACD12B003D12F8 /* UIColor+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Extensions.swift"; sourceTree = "<group>"; };
7BBBDC452875600700747E59 /* DocumentTitleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentTitleViewController.swift; sourceTree = "<group>"; };
7BBBDC43286EAD2D00747E59 /* TappableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TappableLabel.swift; sourceTree = "<group>"; };
7BBBDC452875600700747E59 /* DocumentTitleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentTitleViewController.swift; sourceTree = "<group>"; };
7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SessionNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtension.swift; sourceTree = "<group>"; };
7BC01A3F241F40AB00BC7C55 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -3555,6 +3557,7 @@
FD37EA0E28AB3330003AE748 /* _006_FixHiddenModAdminSupport.swift */,
7B81682728B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift */,
FD09B7E4288670BB00ED0B66 /* _008_EmojiReacts.swift */,
7BAA7B6528D2DE4700AE1489 /* _009_OpenGroupPermission.swift */,
);
path = Migrations;
sourceTree = "<group>";
@ -5314,6 +5317,7 @@
FD09799527FE7B8E00936362 /* Interaction.swift in Sources */,
FD5C72FF284F0F120029977D /* MessageReceiver+ConfigurationMessages.swift in Sources */,
FD37EA0D28AB2A45003AE748 /* _005_FixDeletedMessageReadState.swift in Sources */,
7BAA7B6628D2DE4700AE1489 /* _009_OpenGroupPermission.swift in Sources */,
FDC4380927B31D4E00C60D73 /* OpenGroupAPIError.swift in Sources */,
FDC4382027B36ADC00C60D73 /* SOGSEndpoint.swift in Sources */,
FDC438C927BB706500C60D73 /* SendDirectMessageRequest.swift in Sources */,

View File

@ -920,6 +920,7 @@ extension ConversationVC:
}
func startThread(with sessionId: String, openGroupServer: String?, openGroupPublicKey: String?) {
guard viewModel.threadData.canWrite else { return }
guard SessionId.Prefix(from: sessionId) == .blinded else {
Storage.shared.write { db in
try SessionThread.fetchOrCreate(db, id: sessionId, variant: .contact)

View File

@ -69,10 +69,7 @@ final class ConversationVC: BaseVC, OWSConversationSettingsViewDelegate, Convers
}
override var inputAccessoryView: UIView? {
guard
viewModel.threadData.threadVariant != .closedGroup ||
viewModel.threadData.currentUserIsClosedGroupMember == true
else { return nil }
guard viewModel.threadData.canWrite else { return nil }
return (isShowingSearchUI ? searchController.resultsBar : snInputView)
}
@ -142,10 +139,11 @@ final class ConversationVC: BaseVC, OWSConversationSettingsViewDelegate, Convers
result.showsVerticalScrollIndicator = false
result.contentInsetAdjustmentBehavior = .never
result.keyboardDismissMode = .interactive
let bottomInset: CGFloat = viewModel.threadData.canWrite ? Values.mediumSpacing : Values.mediumSpacing + UIApplication.shared.keyWindow!.safeAreaInsets.bottom
result.contentInset = UIEdgeInsets(
top: 0,
leading: 0,
bottom: Values.mediumSpacing,
bottom: bottomInset,
trailing: 0
)
result.registerHeaderFooterView(view: UITableViewHeaderFooterView.self)

View File

@ -23,6 +23,9 @@ public enum SNMessagingKit { // Just to make the external API nice
],
[
_008_EmojiReacts.self
],
[
_009_OpenGroupPermission.self
]
]
)

View File

@ -0,0 +1,27 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
import SessionUtilitiesKit
enum _009_OpenGroupPermission: Migration {
static let target: TargetMigrations.Identifier = .messagingKit
static let identifier: String = "OpenGroupPermission"
static let needsConfigSync: Bool = false
static let minExpectedRunDuration: TimeInterval = 0.1
static func migrate(_ db: GRDB.Database) throws {
try db.alter(table: OpenGroup.self) { t in
t.add(.permissions, .text)
.defaults(to: OpenGroup.Permission.all.rawValue)
}
// When modifying OpenGroup behaviours we should always look to reset the `infoUpdates`
// value for all OpenGroups to ensure they all have the correct state for newly
// added/changed fields
_ = try OpenGroup
.updateAll(db, OpenGroup.Columns.infoUpdates.set(to: 0))
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
}
}

View File

@ -27,6 +27,14 @@ public struct OpenGroup: Codable, Identifiable, FetchableRecord, PersistableReco
case inboxLatestMessageId
case outboxLatestMessageId
case pollFailureCount
case permissions
}
public enum Permission: String {
case read = "r"
case write = "w"
case upload = "u"
case all = "rwu" // Convenience
}
public var id: String { threadId } // Identifiable
@ -90,6 +98,9 @@ public struct OpenGroup: Codable, Identifiable, FetchableRecord, PersistableReco
/// The number of times this room has failed to poll since the last successful poll
public let pollFailureCount: Int64
/// The permissions this room has for current user
public let permissions: String?
// MARK: - Relationships
public var thread: QueryInterfaceRequest<SessionThread> {
@ -122,7 +133,8 @@ public struct OpenGroup: Codable, Identifiable, FetchableRecord, PersistableReco
sequenceNumber: Int64 = 0,
inboxLatestMessageId: Int64 = 0,
outboxLatestMessageId: Int64 = 0,
pollFailureCount: Int64 = 0
pollFailureCount: Int64 = 0,
permissions: String? = nil
) {
self.threadId = OpenGroup.idFor(roomToken: roomToken, server: server)
self.server = server.lowercased()
@ -139,6 +151,7 @@ public struct OpenGroup: Codable, Identifiable, FetchableRecord, PersistableReco
self.inboxLatestMessageId = inboxLatestMessageId
self.outboxLatestMessageId = outboxLatestMessageId
self.pollFailureCount = pollFailureCount
self.permissions = permissions
}
}
@ -166,7 +179,8 @@ public extension OpenGroup {
sequenceNumber: 0,
inboxLatestMessageId: 0,
outboxLatestMessageId: 0,
pollFailureCount: 0
pollFailureCount: 0,
permissions: nil
)
}
@ -200,7 +214,8 @@ extension OpenGroup: CustomStringConvertible, CustomDebugStringConvertible {
"sequenceNumber: \(sequenceNumber)",
"inboxLatestMessageId: \(inboxLatestMessageId)",
"outboxLatestMessageId: \(outboxLatestMessageId)",
"pollFailureCount: \(pollFailureCount))"
"pollFailureCount: \(pollFailureCount))",
"permissions: \(permissions ?? "null")"
].joined(separator: ", ")
}
}

View File

@ -384,6 +384,11 @@ public final class OpenGroupManager: NSObject {
// Only update the database columns which have changed (this is to prevent the UI from triggering
// updates due to changing database columns to the existing value)
let permissions: String = ""
.appending(pollInfo.read == true ? OpenGroup.Permission.read.rawValue : nil)
.appending(pollInfo.write == true ? OpenGroup.Permission.write.rawValue : nil)
.appending(pollInfo.upload == true ? OpenGroup.Permission.upload.rawValue : nil)
try OpenGroup
.filter(id: openGroup.id)
.updateAll(
@ -412,6 +417,10 @@ public final class OpenGroupManager: NSObject {
(openGroup.infoUpdates != pollInfo.details?.infoUpdates ?
(pollInfo.details?.infoUpdates).map { OpenGroup.Columns.infoUpdates.set(to: $0) } :
nil
),
(openGroup.permissions != permissions ?
OpenGroup.Columns.permissions.set(to: permissions) :
nil
)
].compactMap { $0 }
)

View File

@ -45,6 +45,7 @@ public struct SessionThreadViewModel: FetchableRecordWithRowId, Decodable, Equat
public static let openGroupRoomTokenKey: SQL = SQL(stringLiteral: CodingKeys.openGroupRoomToken.stringValue)
public static let openGroupProfilePictureDataKey: SQL = SQL(stringLiteral: CodingKeys.openGroupProfilePictureData.stringValue)
public static let openGroupUserCountKey: SQL = SQL(stringLiteral: CodingKeys.openGroupUserCount.stringValue)
public static let openGroupPermissionsKey: SQL = SQL(stringLiteral: CodingKeys.openGroupPermissions.stringValue)
public static let interactionIdKey: SQL = SQL(stringLiteral: CodingKeys.interactionId.stringValue)
public static let interactionVariantKey: SQL = SQL(stringLiteral: CodingKeys.interactionVariant.stringValue)
public static let interactionTimestampMsKey: SQL = SQL(stringLiteral: CodingKeys.interactionTimestampMs.stringValue)
@ -94,6 +95,14 @@ public struct SessionThreadViewModel: FetchableRecordWithRowId, Decodable, Equat
public let threadUnreadCount: UInt?
public let threadUnreadMentionCount: UInt?
public var canWrite: Bool {
switch threadVariant {
case .contact: return true
case .closedGroup: return currentUserIsClosedGroupMember == true
case .openGroup: return openGroupPermissions?.range(of: OpenGroup.Permission.write.rawValue) != nil
}
}
// Thread display info
private let contactProfile: Profile?
@ -109,6 +118,7 @@ public struct SessionThreadViewModel: FetchableRecordWithRowId, Decodable, Equat
public let openGroupRoomToken: String?
public let openGroupProfilePictureData: Data?
private let openGroupUserCount: Int?
private let openGroupPermissions: String?
// Interaction display info
@ -262,6 +272,7 @@ public extension SessionThreadViewModel {
self.openGroupRoomToken = nil
self.openGroupProfilePictureData = nil
self.openGroupUserCount = nil
self.openGroupPermissions = nil
// Interaction display info
@ -320,6 +331,7 @@ public extension SessionThreadViewModel {
openGroupRoomToken: self.openGroupRoomToken,
openGroupProfilePictureData: self.openGroupProfilePictureData,
openGroupUserCount: self.openGroupUserCount,
openGroupPermissions: self.openGroupPermissions,
interactionId: self.interactionId,
interactionVariant: self.interactionVariant,
interactionTimestampMs: self.interactionTimestampMs,
@ -371,6 +383,7 @@ public extension SessionThreadViewModel {
openGroupRoomToken: self.openGroupRoomToken,
openGroupProfilePictureData: self.openGroupProfilePictureData,
openGroupUserCount: self.openGroupUserCount,
openGroupPermissions: self.openGroupPermissions,
interactionId: self.interactionId,
interactionVariant: self.interactionVariant,
interactionTimestampMs: self.interactionTimestampMs,
@ -726,6 +739,7 @@ public extension SessionThreadViewModel {
\(openGroup[.server]) AS \(ViewModel.openGroupServerKey),
\(openGroup[.roomToken]) AS \(ViewModel.openGroupRoomTokenKey),
\(openGroup[.userCount]) AS \(ViewModel.openGroupUserCountKey),
\(openGroup[.permissions]) AS \(ViewModel.openGroupPermissionsKey),
\(Interaction.self).\(ViewModel.interactionIdKey),