Cleaning up final things before release
Added basic support for the '25' blinded prefix Fixed a unit test CI issue
This commit is contained in:
parent
f13f75eedf
commit
bc5d8d0931
|
@ -146,7 +146,8 @@ extension ContextMenuVC {
|
|||
for cellViewModel: MessageViewModel,
|
||||
recentEmojis: [EmojiWithSkinTones],
|
||||
currentUserPublicKey: String,
|
||||
currentUserBlindedPublicKey: String?,
|
||||
currentUserBlinded15PublicKey: String?,
|
||||
currentUserBlinded25PublicKey: String?,
|
||||
currentUserIsOpenGroupModerator: Bool,
|
||||
currentThreadIsMessageRequest: Bool,
|
||||
delegate: ContextMenuActionDelegate?
|
||||
|
@ -204,7 +205,8 @@ extension ContextMenuVC {
|
|||
cellViewModel.threadVariant != .community ||
|
||||
currentUserIsOpenGroupModerator ||
|
||||
cellViewModel.authorId == currentUserPublicKey ||
|
||||
cellViewModel.authorId == currentUserBlindedPublicKey ||
|
||||
cellViewModel.authorId == currentUserBlinded15PublicKey ||
|
||||
cellViewModel.authorId == currentUserBlinded25PublicKey ||
|
||||
cellViewModel.state == .failed
|
||||
)
|
||||
let canBan: Bool = (
|
||||
|
|
|
@ -739,7 +739,8 @@ extension ConversationVC:
|
|||
for: cellViewModel,
|
||||
recentEmojis: (self.viewModel.threadData.recentReactionEmoji ?? []).compactMap { EmojiWithSkinTones(rawValue: $0) },
|
||||
currentUserPublicKey: self.viewModel.threadData.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: self.viewModel.threadData.currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: self.viewModel.threadData.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: self.viewModel.threadData.currentUserBlinded25PublicKey,
|
||||
currentUserIsOpenGroupModerator: OpenGroupManager.isUserModeratorOrAdmin(
|
||||
self.viewModel.threadData.currentUserPublicKey,
|
||||
for: self.viewModel.threadData.openGroupRoomToken,
|
||||
|
@ -1018,7 +1019,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 {
|
||||
guard SessionId.Prefix(from: sessionId) == .blinded15 || SessionId.Prefix(from: sessionId) == .blinded25 else {
|
||||
Storage.shared.write { db in
|
||||
try SessionThread
|
||||
.fetchOrCreate(db, id: sessionId, variant: .contact, shouldBeVisible: nil)
|
||||
|
@ -1661,7 +1662,8 @@ extension ConversationVC:
|
|||
attachments: cellViewModel.attachments,
|
||||
linkPreviewAttachment: cellViewModel.linkPreviewAttachment,
|
||||
currentUserPublicKey: cellViewModel.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey
|
||||
currentUserBlinded15PublicKey: cellViewModel.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: cellViewModel.currentUserBlinded25PublicKey
|
||||
)
|
||||
|
||||
guard let quoteDraft: QuotedReplyModel = maybeQuoteDraft else { return }
|
||||
|
|
|
@ -638,7 +638,10 @@ final class ConversationVC: BaseVC, SessionUtilRespondingViewController, Convers
|
|||
// and need to swap over to the new one
|
||||
guard
|
||||
let sessionId: String = self?.viewModel.threadData.threadId,
|
||||
SessionId.Prefix(from: sessionId) == .blinded,
|
||||
(
|
||||
SessionId.Prefix(from: sessionId) == .blinded15 ||
|
||||
SessionId.Prefix(from: sessionId) == .blinded25
|
||||
),
|
||||
let blindedLookup: BlindedIdLookup = Storage.shared.read({ db in
|
||||
try BlindedIdLookup
|
||||
.filter(id: sessionId)
|
||||
|
|
|
@ -71,7 +71,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
threadIsBlocked: Bool,
|
||||
currentUserIsClosedGroupMember: Bool?,
|
||||
openGroupPermissions: OpenGroup.Permissions?,
|
||||
blindedKey: String?
|
||||
blinded15Key: String?,
|
||||
blinded25Key: String?
|
||||
)
|
||||
|
||||
let initialData: InitialData? = Storage.shared.read { db -> InitialData in
|
||||
|
@ -110,10 +111,17 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
.asRequest(of: OpenGroup.Permissions.self)
|
||||
.fetchOne(db)
|
||||
)
|
||||
let blindedKey: String? = SessionThread.getUserHexEncodedBlindedKey(
|
||||
let blinded15Key: String? = SessionThread.getUserHexEncodedBlindedKey(
|
||||
db,
|
||||
threadId: threadId,
|
||||
threadVariant: threadVariant
|
||||
threadVariant: threadVariant,
|
||||
blindingPrefix: .blinded15
|
||||
)
|
||||
let blinded25Key: String? = SessionThread.getUserHexEncodedBlindedKey(
|
||||
db,
|
||||
threadId: threadId,
|
||||
threadVariant: threadVariant,
|
||||
blindingPrefix: .blinded25
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -122,7 +130,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
threadIsBlocked,
|
||||
currentUserIsClosedGroupMember,
|
||||
openGroupPermissions,
|
||||
blindedKey
|
||||
blinded15Key,
|
||||
blinded25Key
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -138,7 +147,10 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
threadIsBlocked: initialData?.threadIsBlocked,
|
||||
currentUserIsClosedGroupMember: initialData?.currentUserIsClosedGroupMember,
|
||||
openGroupPermissions: initialData?.openGroupPermissions
|
||||
).populatingCurrentUserBlindedKey(currentUserBlindedPublicKeyForThisThread: initialData?.blindedKey)
|
||||
).populatingCurrentUserBlindedKeys(
|
||||
currentUserBlinded15PublicKeyForThisThread: initialData?.blinded15Key,
|
||||
currentUserBlinded25PublicKeyForThisThread: initialData?.blinded25Key
|
||||
)
|
||||
self.pagedDataObserver = nil
|
||||
|
||||
// Note: Since this references self we need to finish initializing before setting it, we
|
||||
|
@ -148,10 +160,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
self.pagedDataObserver = self.setupPagedObserver(
|
||||
for: threadId,
|
||||
userPublicKey: (initialData?.currentUserPublicKey ?? getUserHexEncodedPublicKey()),
|
||||
blindedPublicKey: SessionThread.getUserHexEncodedBlindedKey(
|
||||
threadId: threadId,
|
||||
threadVariant: threadVariant
|
||||
)
|
||||
blinded15PublicKey: initialData?.blinded15Key,
|
||||
blinded25PublicKey: initialData?.blinded25Key
|
||||
)
|
||||
|
||||
// Run the initial query on a background thread so we don't block the push transition
|
||||
|
@ -197,9 +207,10 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
return threadViewModel
|
||||
.map { $0.with(recentReactionEmoji: recentReactionEmoji) }
|
||||
.map { viewModel -> SessionThreadViewModel in
|
||||
viewModel.populatingCurrentUserBlindedKey(
|
||||
viewModel.populatingCurrentUserBlindedKeys(
|
||||
db,
|
||||
currentUserBlindedPublicKeyForThisThread: self?.threadData.currentUserBlindedPublicKey
|
||||
currentUserBlinded15PublicKeyForThisThread: self?.threadData.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKeyForThisThread: self?.threadData.currentUserBlinded25PublicKey
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -237,7 +248,12 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
private func setupPagedObserver(for threadId: String, userPublicKey: String, blindedPublicKey: String?) -> PagedDatabaseObserver<Interaction, MessageViewModel> {
|
||||
private func setupPagedObserver(
|
||||
for threadId: String,
|
||||
userPublicKey: String,
|
||||
blinded15PublicKey: String?,
|
||||
blinded25PublicKey: String?
|
||||
) -> PagedDatabaseObserver<Interaction, MessageViewModel> {
|
||||
return PagedDatabaseObserver(
|
||||
pagedTable: Interaction.self,
|
||||
pageSize: ConversationViewModel.pageSize,
|
||||
|
@ -285,7 +301,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
orderSQL: MessageViewModel.orderSQL,
|
||||
dataQuery: MessageViewModel.baseQuery(
|
||||
userPublicKey: userPublicKey,
|
||||
blindedPublicKey: blindedPublicKey,
|
||||
blinded15PublicKey: blinded15PublicKey,
|
||||
blinded25PublicKey: blinded25PublicKey,
|
||||
orderSQL: MessageViewModel.orderSQL,
|
||||
groupSQL: MessageViewModel.groupSQL
|
||||
),
|
||||
|
@ -391,12 +408,14 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
cellViewModel.id == sortedData
|
||||
.filter {
|
||||
$0.authorId == threadData.currentUserPublicKey ||
|
||||
$0.authorId == threadData.currentUserBlindedPublicKey
|
||||
$0.authorId == threadData.currentUserBlinded15PublicKey ||
|
||||
$0.authorId == threadData.currentUserBlinded25PublicKey
|
||||
}
|
||||
.last?
|
||||
.id
|
||||
),
|
||||
currentUserBlindedPublicKey: threadData.currentUserBlindedPublicKey
|
||||
currentUserBlinded15PublicKey: threadData.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: threadData.currentUserBlinded25PublicKey
|
||||
)
|
||||
}
|
||||
.reduce([]) { result, message in
|
||||
|
@ -460,14 +479,15 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
let currentUserProfile: Profile = Profile.fetchOrCreateCurrentUser()
|
||||
let interaction: Interaction = Interaction(
|
||||
threadId: threadData.threadId,
|
||||
authorId: (threadData.currentUserBlindedPublicKey ?? threadData.currentUserPublicKey),
|
||||
authorId: (threadData.currentUserBlinded15PublicKey ?? threadData.currentUserPublicKey),
|
||||
variant: .standardOutgoing,
|
||||
body: text,
|
||||
timestampMs: sentTimestampMs,
|
||||
hasMention: Interaction.isUserMentioned(
|
||||
publicKeysToCheck: [
|
||||
threadData.currentUserPublicKey,
|
||||
threadData.currentUserBlindedPublicKey
|
||||
threadData.currentUserBlinded15PublicKey,
|
||||
threadData.currentUserBlinded25PublicKey
|
||||
].compactMap { $0 },
|
||||
body: text
|
||||
),
|
||||
|
@ -601,9 +621,9 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
.fetchSet(db)
|
||||
)
|
||||
.defaulting(to: [])
|
||||
let targetPrefix: SessionId.Prefix = (capabilities.contains(.blind) ?
|
||||
.blinded :
|
||||
.standard
|
||||
let targetPrefixes: [SessionId.Prefix] = (capabilities.contains(.blind) ?
|
||||
[.blinded15, .blinded25] :
|
||||
[.standard]
|
||||
)
|
||||
|
||||
return (try MentionInfo
|
||||
|
@ -611,7 +631,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
userPublicKey: userPublicKey,
|
||||
threadId: threadData.threadId,
|
||||
threadVariant: threadData.threadVariant,
|
||||
targetPrefix: targetPrefix,
|
||||
targetPrefixes: targetPrefixes,
|
||||
pattern: pattern
|
||||
)?
|
||||
.fetchAll(db))
|
||||
|
@ -706,7 +726,8 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
|
|||
self.pagedDataObserver = self.setupPagedObserver(
|
||||
for: updatedThreadId,
|
||||
userPublicKey: getUserHexEncodedPublicKey(),
|
||||
blindedPublicKey: nil
|
||||
blinded15PublicKey: nil,
|
||||
blinded25PublicKey: nil
|
||||
)
|
||||
|
||||
// Try load everything up to the initial visible message, fallback to just the initial page of messages
|
||||
|
|
|
@ -265,7 +265,8 @@ final class InputView: UIView, InputViewButtonDelegate, InputTextViewDelegate, M
|
|||
quotedText: quoteDraftInfo.model.body,
|
||||
threadVariant: threadVariant,
|
||||
currentUserPublicKey: quoteDraftInfo.model.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: quoteDraftInfo.model.currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: quoteDraftInfo.model.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: quoteDraftInfo.model.currentUserBlinded25PublicKey,
|
||||
direction: (quoteDraftInfo.isOutgoing ? .outgoing : .incoming),
|
||||
attachment: quoteDraftInfo.model.attachment,
|
||||
hInset: hInset,
|
||||
|
|
|
@ -30,7 +30,8 @@ final class QuoteView: UIView {
|
|||
quotedText: String?,
|
||||
threadVariant: SessionThread.Variant,
|
||||
currentUserPublicKey: String?,
|
||||
currentUserBlindedPublicKey: String?,
|
||||
currentUserBlinded15PublicKey: String?,
|
||||
currentUserBlinded25PublicKey: String?,
|
||||
direction: Direction,
|
||||
attachment: Attachment?,
|
||||
hInset: CGFloat,
|
||||
|
@ -47,7 +48,8 @@ final class QuoteView: UIView {
|
|||
quotedText: quotedText,
|
||||
threadVariant: threadVariant,
|
||||
currentUserPublicKey: currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: currentUserBlinded25PublicKey,
|
||||
direction: direction,
|
||||
attachment: attachment,
|
||||
hInset: hInset,
|
||||
|
@ -69,7 +71,8 @@ final class QuoteView: UIView {
|
|||
quotedText: String?,
|
||||
threadVariant: SessionThread.Variant,
|
||||
currentUserPublicKey: String?,
|
||||
currentUserBlindedPublicKey: String?,
|
||||
currentUserBlinded15PublicKey: String?,
|
||||
currentUserBlinded25PublicKey: String?,
|
||||
direction: Direction,
|
||||
attachment: Attachment?,
|
||||
hInset: CGFloat,
|
||||
|
@ -211,7 +214,8 @@ final class QuoteView: UIView {
|
|||
in: $0,
|
||||
threadVariant: threadVariant,
|
||||
currentUserPublicKey: currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: currentUserBlinded25PublicKey,
|
||||
isOutgoingMessage: (direction == .outgoing),
|
||||
textColor: textColor,
|
||||
theme: theme,
|
||||
|
@ -234,7 +238,8 @@ final class QuoteView: UIView {
|
|||
|
||||
let isCurrentUser: Bool = [
|
||||
currentUserPublicKey,
|
||||
currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey
|
||||
]
|
||||
.compactMap { $0 }
|
||||
.asSet()
|
||||
|
|
|
@ -542,7 +542,8 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
|
|||
quotedText: quote.body,
|
||||
threadVariant: cellViewModel.threadVariant,
|
||||
currentUserPublicKey: cellViewModel.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: cellViewModel.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: cellViewModel.currentUserBlinded25PublicKey,
|
||||
direction: (cellViewModel.variant == .standardOutgoing ?
|
||||
.outgoing :
|
||||
.incoming
|
||||
|
@ -868,7 +869,10 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
|
|||
if profilePictureView.bounds.contains(profilePictureView.convert(location, from: self)), cellViewModel.shouldShowProfile {
|
||||
// For open groups only attempt to start a conversation if the author has a blinded id
|
||||
guard cellViewModel.threadVariant != .community else {
|
||||
guard SessionId.Prefix(from: cellViewModel.authorId) == .blinded else { return }
|
||||
guard
|
||||
SessionId.Prefix(from: cellViewModel.authorId) == .blinded15 ||
|
||||
SessionId.Prefix(from: cellViewModel.authorId) == .blinded25
|
||||
else { return }
|
||||
|
||||
delegate?.startThread(
|
||||
with: cellViewModel.authorId,
|
||||
|
@ -1118,7 +1122,8 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
|
|||
in: (cellViewModel.body ?? ""),
|
||||
threadVariant: cellViewModel.threadVariant,
|
||||
currentUserPublicKey: cellViewModel.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: cellViewModel.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: cellViewModel.currentUserBlinded25PublicKey,
|
||||
isOutgoingMessage: isOutgoing,
|
||||
textColor: actualTextColor,
|
||||
theme: theme,
|
||||
|
|
|
@ -704,13 +704,15 @@ final class HomeVC: BaseVC, SessionUtilRespondingViewController, UITableViewData
|
|||
|
||||
// Cannot properly sync outgoing blinded message requests so only provide valid options
|
||||
let shouldHavePinAction: Bool = (
|
||||
sessionIdPrefix != .blinded
|
||||
sessionIdPrefix != .blinded15 &&
|
||||
sessionIdPrefix != .blinded25
|
||||
)
|
||||
let shouldHaveMuteAction: Bool = {
|
||||
switch threadViewModel.threadVariant {
|
||||
case .contact: return (
|
||||
!threadViewModel.threadIsNoteToSelf &&
|
||||
sessionIdPrefix != .blinded
|
||||
sessionIdPrefix != .blinded15 &&
|
||||
sessionIdPrefix != .blinded25
|
||||
)
|
||||
|
||||
case .legacyGroup, .group: return (
|
||||
|
|
|
@ -361,10 +361,13 @@ public class HomeViewModel {
|
|||
return lhs.lastInteractionDate > rhs.lastInteractionDate
|
||||
}
|
||||
.map { viewModel -> SessionThreadViewModel in
|
||||
viewModel.populatingCurrentUserBlindedKey(
|
||||
currentUserBlindedPublicKeyForThisThread: groupedOldData[viewModel.threadId]?
|
||||
viewModel.populatingCurrentUserBlindedKeys(
|
||||
currentUserBlinded15PublicKeyForThisThread: groupedOldData[viewModel.threadId]?
|
||||
.first?
|
||||
.currentUserBlindedPublicKey
|
||||
.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKeyForThisThread: groupedOldData[viewModel.threadId]?
|
||||
.first?
|
||||
.currentUserBlinded25PublicKey
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -156,10 +156,13 @@ public class MessageRequestsViewModel {
|
|||
elements: data
|
||||
.sorted { lhs, rhs -> Bool in lhs.lastInteractionDate > rhs.lastInteractionDate }
|
||||
.map { viewModel -> SessionThreadViewModel in
|
||||
viewModel.populatingCurrentUserBlindedKey(
|
||||
currentUserBlindedPublicKeyForThisThread: groupedOldData[viewModel.threadId]?
|
||||
viewModel.populatingCurrentUserBlindedKeys(
|
||||
currentUserBlinded15PublicKeyForThisThread: groupedOldData[viewModel.threadId]?
|
||||
.first?
|
||||
.currentUserBlindedPublicKey
|
||||
.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKeyForThisThread: groupedOldData[viewModel.threadId]?
|
||||
.first?
|
||||
.currentUserBlinded25PublicKey
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -178,7 +178,7 @@ final class NewDMVC: BaseVC, UIPageViewControllerDataSource, UIPageViewControlle
|
|||
case .standard:
|
||||
startNewDM(with: onsNameOrPublicKey)
|
||||
|
||||
case .blinded:
|
||||
case .blinded15, .blinded25:
|
||||
let modal: ConfirmationModal = ConfirmationModal(
|
||||
targetView: self.view,
|
||||
info: ConfirmationModal.Info(
|
||||
|
@ -233,7 +233,7 @@ final class NewDMVC: BaseVC, UIPageViewControllerDataSource, UIPageViewControlle
|
|||
return messageOrNil
|
||||
}
|
||||
|
||||
return (maybeSessionId?.prefix == .blinded ?
|
||||
return (maybeSessionId?.prefix == .blinded15 || maybeSessionId?.prefix == .blinded25 ?
|
||||
"DM_ERROR_DIRECT_BLINDED_ID".localized() :
|
||||
"DM_ERROR_INVALID".localized()
|
||||
)
|
||||
|
|
|
@ -239,10 +239,17 @@ public class NotificationPresenter: NotificationsProtocol {
|
|||
]
|
||||
|
||||
let userPublicKey: String = getUserHexEncodedPublicKey(db)
|
||||
let userBlindedKey: String? = SessionThread.getUserHexEncodedBlindedKey(
|
||||
let userBlinded15Key: String? = SessionThread.getUserHexEncodedBlindedKey(
|
||||
db,
|
||||
threadId: thread.id,
|
||||
threadVariant: thread.variant
|
||||
threadVariant: thread.variant,
|
||||
blindingPrefix: .blinded15
|
||||
)
|
||||
let userBlinded25Key: String? = SessionThread.getUserHexEncodedBlindedKey(
|
||||
db,
|
||||
threadId: thread.id,
|
||||
threadVariant: thread.variant,
|
||||
blindingPrefix: .blinded25
|
||||
)
|
||||
let fallbackSound: Preferences.Sound = db[.defaultNotificationSound]
|
||||
.defaulting(to: Preferences.Sound.defaultNotificationSound)
|
||||
|
@ -257,7 +264,8 @@ public class NotificationPresenter: NotificationsProtocol {
|
|||
in: (notificationBody ?? ""),
|
||||
threadVariant: thread.variant,
|
||||
currentUserPublicKey: userPublicKey,
|
||||
currentUserBlindedPublicKey: userBlindedKey
|
||||
currentUserBlinded15PublicKey: userBlinded15Key,
|
||||
currentUserBlinded25PublicKey: userBlinded25Key
|
||||
)
|
||||
|
||||
self.adaptee.notify(
|
||||
|
|
|
@ -310,7 +310,8 @@ public final class FullConversationCell: UITableViewCell, SwipeActionOptimisticC
|
|||
nil
|
||||
),
|
||||
currentUserPublicKey: cellViewModel.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: cellViewModel.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: cellViewModel.currentUserBlinded25PublicKey,
|
||||
searchText: searchText.lowercased(),
|
||||
fontSize: Values.smallFontSize,
|
||||
textColor: textColor
|
||||
|
@ -339,7 +340,8 @@ public final class FullConversationCell: UITableViewCell, SwipeActionOptimisticC
|
|||
displayNameLabel?.attributedText = self?.getHighlightedSnippet(
|
||||
content: cellViewModel.displayName,
|
||||
currentUserPublicKey: cellViewModel.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: cellViewModel.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: cellViewModel.currentUserBlinded25PublicKey,
|
||||
searchText: searchText.lowercased(),
|
||||
fontSize: Values.mediumFontSize,
|
||||
textColor: textColor
|
||||
|
@ -358,7 +360,8 @@ public final class FullConversationCell: UITableViewCell, SwipeActionOptimisticC
|
|||
snippetLabel?.attributedText = self?.getHighlightedSnippet(
|
||||
content: (cellViewModel.threadMemberNames ?? ""),
|
||||
currentUserPublicKey: cellViewModel.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: cellViewModel.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: cellViewModel.currentUserBlinded25PublicKey,
|
||||
searchText: searchText.lowercased(),
|
||||
fontSize: Values.smallFontSize,
|
||||
textColor: textColor
|
||||
|
@ -598,7 +601,8 @@ public final class FullConversationCell: UITableViewCell, SwipeActionOptimisticC
|
|||
in: previewText,
|
||||
threadVariant: cellViewModel.threadVariant,
|
||||
currentUserPublicKey: cellViewModel.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: cellViewModel.currentUserBlindedPublicKey
|
||||
currentUserBlinded15PublicKey: cellViewModel.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: cellViewModel.currentUserBlinded25PublicKey
|
||||
),
|
||||
attributes: [ .foregroundColor: textColor ]
|
||||
))
|
||||
|
@ -610,7 +614,8 @@ public final class FullConversationCell: UITableViewCell, SwipeActionOptimisticC
|
|||
content: String,
|
||||
authorName: String? = nil,
|
||||
currentUserPublicKey: String,
|
||||
currentUserBlindedPublicKey: String?,
|
||||
currentUserBlinded15PublicKey: String?,
|
||||
currentUserBlinded25PublicKey: String?,
|
||||
searchText: String,
|
||||
fontSize: CGFloat,
|
||||
textColor: UIColor
|
||||
|
@ -633,7 +638,8 @@ public final class FullConversationCell: UITableViewCell, SwipeActionOptimisticC
|
|||
in: content,
|
||||
threadVariant: .contact,
|
||||
currentUserPublicKey: currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: currentUserBlindedPublicKey
|
||||
currentUserBlinded15PublicKey: currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: currentUserBlinded25PublicKey
|
||||
)
|
||||
let result: NSMutableAttributedString = NSMutableAttributedString(
|
||||
string: mentionReplacedContent,
|
||||
|
|
|
@ -10,14 +10,16 @@ public enum MentionUtilities {
|
|||
in string: String,
|
||||
threadVariant: SessionThread.Variant,
|
||||
currentUserPublicKey: String,
|
||||
currentUserBlindedPublicKey: String?
|
||||
currentUserBlinded15PublicKey: String?,
|
||||
currentUserBlinded25PublicKey: String?
|
||||
) -> String {
|
||||
/// **Note:** We are returning the string here so the 'textColor' and 'primaryColor' values are irrelevant
|
||||
return highlightMentions(
|
||||
in: string,
|
||||
threadVariant: threadVariant,
|
||||
currentUserPublicKey: currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: currentUserBlinded25PublicKey,
|
||||
isOutgoingMessage: false,
|
||||
textColor: .black,
|
||||
theme: .classicDark,
|
||||
|
@ -30,7 +32,8 @@ public enum MentionUtilities {
|
|||
in string: String,
|
||||
threadVariant: SessionThread.Variant,
|
||||
currentUserPublicKey: String?,
|
||||
currentUserBlindedPublicKey: String?,
|
||||
currentUserBlinded15PublicKey: String?,
|
||||
currentUserBlinded25PublicKey: String?,
|
||||
isOutgoingMessage: Bool,
|
||||
textColor: UIColor,
|
||||
theme: Theme,
|
||||
|
@ -48,7 +51,8 @@ public enum MentionUtilities {
|
|||
var mentions: [(range: NSRange, isCurrentUser: Bool)] = []
|
||||
let currentUserPublicKeys: Set<String> = [
|
||||
currentUserPublicKey,
|
||||
currentUserBlindedPublicKey
|
||||
currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey
|
||||
]
|
||||
.compactMap { $0 }
|
||||
.asSet()
|
||||
|
|
|
@ -815,9 +815,8 @@ public extension Interaction {
|
|||
genericHash: sodium.genericHash
|
||||
)
|
||||
{
|
||||
publicKeysToCheck.append(
|
||||
SessionId(.blinded, publicKey: blindedKeyPair.publicKey).hexString
|
||||
)
|
||||
publicKeysToCheck.append(SessionId(.blinded15, publicKey: blindedKeyPair.publicKey).hexString)
|
||||
publicKeysToCheck.append(SessionId(.blinded25, publicKey: blindedKeyPair.publicKey).hexString)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -524,12 +524,13 @@ public extension SessionThread {
|
|||
static func getUserHexEncodedBlindedKey(
|
||||
_ db: Database? = nil,
|
||||
threadId: String,
|
||||
threadVariant: Variant
|
||||
threadVariant: Variant,
|
||||
blindingPrefix: SessionId.Prefix
|
||||
) -> String? {
|
||||
guard threadVariant == .community else { return nil }
|
||||
guard let db: Database = db else {
|
||||
return Storage.shared.read { db in
|
||||
getUserHexEncodedBlindedKey(db, threadId: threadId, threadVariant: threadVariant)
|
||||
getUserHexEncodedBlindedKey(db, threadId: threadId, threadVariant: threadVariant, blindingPrefix: blindingPrefix)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,7 +568,7 @@ public extension SessionThread {
|
|||
)
|
||||
|
||||
return blindedKeyPair.map { keyPair -> String in
|
||||
SessionId(.blinded, publicKey: keyPair.publicKey).hexString
|
||||
SessionId(blindingPrefix, publicKey: keyPair.publicKey).hexString
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,9 @@ public extension Message {
|
|||
) throws -> Message.Destination {
|
||||
switch threadVariant {
|
||||
case .contact:
|
||||
if SessionId.Prefix(from: threadId) == .blinded {
|
||||
let prefix: SessionId.Prefix? = SessionId.Prefix(from: threadId)
|
||||
|
||||
if prefix == .blinded15 || prefix == .blinded25 {
|
||||
guard let lookup: BlindedIdLookup = try? BlindedIdLookup.fetchOne(db, id: threadId) else {
|
||||
preconditionFailure("Attempting to send message to blinded id without the Open Group information")
|
||||
}
|
||||
|
|
|
@ -404,12 +404,21 @@ public extension Message {
|
|||
var results: [Reaction] = []
|
||||
guard let reactions = message.reactions else { return results }
|
||||
let userPublicKey: String = getUserHexEncodedPublicKey(db)
|
||||
let blindedUserPublicKey: String? = SessionThread
|
||||
let blinded15UserPublicKey: String? = SessionThread
|
||||
.getUserHexEncodedBlindedKey(
|
||||
db,
|
||||
threadId: openGroupId,
|
||||
threadVariant: .community
|
||||
threadVariant: .community,
|
||||
blindingPrefix: .blinded15
|
||||
)
|
||||
let blinded25UserPublicKey: String? = SessionThread
|
||||
.getUserHexEncodedBlindedKey(
|
||||
db,
|
||||
threadId: openGroupId,
|
||||
threadVariant: .community,
|
||||
blindingPrefix: .blinded25
|
||||
)
|
||||
|
||||
for (encodedEmoji, rawReaction) in reactions {
|
||||
if let decodedEmoji = encodedEmoji.removingPercentEncoding,
|
||||
rawReaction.count > 0,
|
||||
|
@ -456,7 +465,11 @@ public extension Message {
|
|||
let timestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs()
|
||||
let maxLength: Int = shouldAddSelfReaction ? 4 : 5
|
||||
let desiredReactorIds: [String] = reactors
|
||||
.filter { $0 != blindedUserPublicKey && $0 != userPublicKey } // Remove current user for now, will add back if needed
|
||||
.filter { id -> Bool in
|
||||
id != blinded15UserPublicKey &&
|
||||
id != blinded25UserPublicKey &&
|
||||
id != userPublicKey
|
||||
} // Remove current user for now, will add back if needed
|
||||
.prefix(maxLength)
|
||||
.map{ $0 }
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ extension OpenGroupAPI.Message {
|
|||
let publicKey: Data = Data(hex: sender.removingIdPrefixIfNeeded())
|
||||
|
||||
switch SessionId.Prefix(from: sender) {
|
||||
case .blinded:
|
||||
case .blinded15, .blinded25:
|
||||
guard dependencies.sign.verify(message: data.bytes, publicKey: publicKey.bytes, signature: signature.bytes) else {
|
||||
SNLog("Ignoring message with invalid signature.")
|
||||
throw HTTPError.parsingFailed
|
||||
|
|
|
@ -1237,7 +1237,7 @@ public enum OpenGroupAPI {
|
|||
}
|
||||
|
||||
return (
|
||||
publicKey: SessionId(.blinded, publicKey: blindedKeyPair.publicKey).hexString,
|
||||
publicKey: SessionId(.blinded15, publicKey: blindedKeyPair.publicKey).hexString,
|
||||
signature: signatureResult
|
||||
)
|
||||
}
|
||||
|
|
|
@ -927,7 +927,7 @@ public final class OpenGroupManager {
|
|||
let targetRoles: [GroupMember.Role] = [.moderator, .admin]
|
||||
|
||||
return dependencies.storage
|
||||
.read { db in
|
||||
.read { db -> Bool in
|
||||
let isDirectModOrAdmin: Bool = GroupMember
|
||||
.filter(GroupMember.Columns.groupId == groupId)
|
||||
.filter(GroupMember.Columns.profileId == publicKey)
|
||||
|
@ -959,7 +959,7 @@ public final class OpenGroupManager {
|
|||
}
|
||||
fallthrough
|
||||
|
||||
case .blinded:
|
||||
case .blinded15, .blinded25:
|
||||
guard
|
||||
let userEdKeyPair: KeyPair = Identity.fetchUserEd25519KeyPair(db),
|
||||
let openGroupPublicKey: String = try? OpenGroup
|
||||
|
@ -973,9 +973,14 @@ public final class OpenGroupManager {
|
|||
genericHash: dependencies.genericHash
|
||||
)
|
||||
else { return false }
|
||||
guard sessionId.prefix != .blinded || publicKey == SessionId(.blinded, publicKey: blindedKeyPair.publicKey).hexString else {
|
||||
return false
|
||||
}
|
||||
guard
|
||||
(
|
||||
sessionId.prefix != .blinded15 &&
|
||||
sessionId.prefix != .blinded25
|
||||
) ||
|
||||
publicKey == SessionId(.blinded15, publicKey: blindedKeyPair.publicKey).hexString ||
|
||||
publicKey == SessionId(.blinded25, publicKey: blindedKeyPair.publicKey).hexString
|
||||
else { return false }
|
||||
|
||||
// If we got to here that means that the 'publicKey' value matches one of the current
|
||||
// users 'standard', 'unblinded' or 'blinded' keys and as such we should check if any
|
||||
|
@ -983,7 +988,8 @@ public final class OpenGroupManager {
|
|||
let possibleKeys: Set<String> = Set([
|
||||
userPublicKey,
|
||||
SessionId(.unblinded, publicKey: userEdKeyPair.publicKey).hexString,
|
||||
SessionId(.blinded, publicKey: blindedKeyPair.publicKey).hexString
|
||||
SessionId(.blinded15, publicKey: blindedKeyPair.publicKey).hexString,
|
||||
SessionId(.blinded25, publicKey: blindedKeyPair.publicKey).hexString
|
||||
])
|
||||
|
||||
return GroupMember
|
||||
|
|
|
@ -79,7 +79,7 @@ extension MessageReceiver {
|
|||
|
||||
// If the contact is a blinded contact then only add them if they haven't already been
|
||||
// unblinded
|
||||
if SessionId.Prefix(from: sessionId) == .blinded {
|
||||
if SessionId.Prefix(from: sessionId) == .blinded15 || SessionId.Prefix(from: sessionId) == .blinded25 {
|
||||
let hasUnblindedContact: Bool = BlindedIdLookup
|
||||
.filter(BlindedIdLookup.Columns.blindedId == sessionId)
|
||||
.filter(BlindedIdLookup.Columns.sessionId != nil)
|
||||
|
|
|
@ -55,7 +55,10 @@ extension MessageReceiver {
|
|||
let blindedThreadIds: Set<String> = (try? SessionThread
|
||||
.select(.id)
|
||||
.filter(SessionThread.Columns.variant == SessionThread.Variant.contact)
|
||||
.filter(SessionThread.Columns.id.like("\(SessionId.Prefix.blinded.rawValue)%"))
|
||||
.filter(
|
||||
SessionThread.Columns.id.like("\(SessionId.Prefix.blinded15.rawValue)%") ||
|
||||
SessionThread.Columns.id.like("\(SessionId.Prefix.blinded25.rawValue)%")
|
||||
)
|
||||
.asRequest(of: String.self)
|
||||
.fetchSet(db))
|
||||
.defaulting(to: [])
|
||||
|
|
|
@ -85,7 +85,7 @@ extension MessageReceiver {
|
|||
|
||||
// Need to check if the blinded id matches for open groups
|
||||
switch senderSessionId.prefix {
|
||||
case .blinded:
|
||||
case .blinded15, .blinded25:
|
||||
let sodium: Sodium = Sodium()
|
||||
|
||||
guard
|
||||
|
@ -97,7 +97,12 @@ extension MessageReceiver {
|
|||
)
|
||||
else { return .standardIncoming }
|
||||
|
||||
return (sender == SessionId(.blinded, publicKey: blindedKeyPair.publicKey).hexString ?
|
||||
let senderIdCurrentUserBlinded: Bool = (
|
||||
sender == SessionId(.blinded15, publicKey: blindedKeyPair.publicKey).hexString ||
|
||||
sender == SessionId(.blinded25, publicKey: blindedKeyPair.publicKey).hexString
|
||||
)
|
||||
|
||||
return (senderIdCurrentUserBlinded ?
|
||||
.standardOutgoing :
|
||||
.standardIncoming
|
||||
)
|
||||
|
|
|
@ -45,7 +45,7 @@ public enum MessageReceiver {
|
|||
|
||||
(plaintext, sender) = try decryptWithSessionProtocol(ciphertext: ciphertext, using: userX25519KeyPair)
|
||||
|
||||
case .blinded:
|
||||
case .blinded15, .blinded25:
|
||||
guard let otherBlindedPublicKey: String = otherBlindedPublicKey else {
|
||||
throw MessageReceiverError.noData
|
||||
}
|
||||
|
|
|
@ -38,9 +38,10 @@ extension MessageSender {
|
|||
openGroupPublicKey: String,
|
||||
using dependencies: SMKDependencies = SMKDependencies()
|
||||
) throws -> Data {
|
||||
guard SessionId.Prefix(from: recipientBlindedId) == .blinded else {
|
||||
throw MessageSenderError.signingFailed
|
||||
}
|
||||
guard
|
||||
SessionId.Prefix(from: recipientBlindedId) == .blinded15 ||
|
||||
SessionId.Prefix(from: recipientBlindedId) == .blinded25
|
||||
else { throw MessageSenderError.signingFailed }
|
||||
guard let userEd25519KeyPair: KeyPair = Identity.fetchUserEd25519KeyPair(db) else {
|
||||
throw MessageSenderError.noUserED25519KeyPair
|
||||
}
|
||||
|
|
|
@ -411,7 +411,7 @@ public final class MessageSender {
|
|||
preconditionFailure()
|
||||
}
|
||||
|
||||
return SessionId(.blinded, publicKey: blindedKeyPair.publicKey).hexString
|
||||
return SessionId(.blinded15, publicKey: blindedKeyPair.publicKey).hexString
|
||||
}()
|
||||
|
||||
// Validate the message
|
||||
|
|
|
@ -13,7 +13,8 @@ public struct QuotedReplyModel {
|
|||
public let sourceFileName: String?
|
||||
public let thumbnailDownloadFailed: Bool
|
||||
public let currentUserPublicKey: String?
|
||||
public let currentUserBlindedPublicKey: String?
|
||||
public let currentUserBlinded15PublicKey: String?
|
||||
public let currentUserBlinded25PublicKey: String?
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
|
@ -27,7 +28,8 @@ public struct QuotedReplyModel {
|
|||
sourceFileName: String?,
|
||||
thumbnailDownloadFailed: Bool,
|
||||
currentUserPublicKey: String?,
|
||||
currentUserBlindedPublicKey: String?
|
||||
currentUserBlinded15PublicKey: String?,
|
||||
currentUserBlinded25PublicKey: String?
|
||||
) {
|
||||
self.attachment = attachment
|
||||
self.threadId = threadId
|
||||
|
@ -38,7 +40,8 @@ public struct QuotedReplyModel {
|
|||
self.sourceFileName = sourceFileName
|
||||
self.thumbnailDownloadFailed = thumbnailDownloadFailed
|
||||
self.currentUserPublicKey = currentUserPublicKey
|
||||
self.currentUserBlindedPublicKey = currentUserBlindedPublicKey
|
||||
self.currentUserBlinded15PublicKey = currentUserBlinded15PublicKey
|
||||
self.currentUserBlinded25PublicKey = currentUserBlinded25PublicKey
|
||||
}
|
||||
|
||||
public static func quotedReplyForSending(
|
||||
|
@ -50,7 +53,8 @@ public struct QuotedReplyModel {
|
|||
attachments: [Attachment]?,
|
||||
linkPreviewAttachment: Attachment?,
|
||||
currentUserPublicKey: String?,
|
||||
currentUserBlindedPublicKey: String?
|
||||
currentUserBlinded15PublicKey: String?,
|
||||
currentUserBlinded25PublicKey: String?
|
||||
) -> QuotedReplyModel? {
|
||||
guard variant == .standardOutgoing || variant == .standardIncoming else { return nil }
|
||||
guard (body != nil && body?.isEmpty == false) || attachments?.isEmpty == false else { return nil }
|
||||
|
@ -67,7 +71,8 @@ public struct QuotedReplyModel {
|
|||
sourceFileName: targetAttachment?.sourceFilename,
|
||||
thumbnailDownloadFailed: false,
|
||||
currentUserPublicKey: currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: currentUserBlindedPublicKey
|
||||
currentUserBlinded15PublicKey: currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: currentUserBlinded25PublicKey
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -193,7 +193,8 @@ internal extension SessionUtil {
|
|||
let threadIdsToRemove: [String] = try SessionThread
|
||||
.filter(!syncedContactIds.contains(SessionThread.Columns.id))
|
||||
.filter(SessionThread.Columns.variant == SessionThread.Variant.contact)
|
||||
.filter(!SessionThread.Columns.id.like("\(SessionId.Prefix.blinded.rawValue)%"))
|
||||
.filter(!SessionThread.Columns.id.like("\(SessionId.Prefix.blinded15.rawValue)%"))
|
||||
.filter(!SessionThread.Columns.id.like("\(SessionId.Prefix.blinded25.rawValue)%"))
|
||||
.select(.id)
|
||||
.asRequest(of: String.self)
|
||||
.fetchAll(db)
|
||||
|
|
|
@ -21,7 +21,7 @@ public extension MentionInfo {
|
|||
userPublicKey: String,
|
||||
threadId: String,
|
||||
threadVariant: SessionThread.Variant,
|
||||
targetPrefix: SessionId.Prefix,
|
||||
targetPrefixes: [SessionId.Prefix],
|
||||
pattern: FTS5Pattern?
|
||||
) -> AdaptedFetchRequest<SQLRequest<MentionInfo>>? {
|
||||
guard threadVariant != .contact || userPublicKey != threadId else { return nil }
|
||||
|
@ -31,7 +31,9 @@ public extension MentionInfo {
|
|||
let openGroup: TypedTableAlias<OpenGroup> = TypedTableAlias()
|
||||
let groupMember: TypedTableAlias<GroupMember> = TypedTableAlias()
|
||||
|
||||
let prefixLiteral: SQL = SQL(stringLiteral: "\(targetPrefix.rawValue)%")
|
||||
let prefixesLiteral: SQLExpression = targetPrefixes
|
||||
.map { SQL("\(profile[.id]) LIKE '\(SQL(stringLiteral: "\($0.rawValue)%"))'") }
|
||||
.joined(operator: .or)
|
||||
let profileFullTextSearch: SQL = SQL(stringLiteral: Profile.fullTextSearchTableName)
|
||||
|
||||
/// The query needs to differ depending on the thread variant because the behaviour should be different:
|
||||
|
@ -50,7 +52,7 @@ public extension MentionInfo {
|
|||
\(Profile.self).rowid = \(profileFullTextSearch).rowid AND
|
||||
\(SQL("\(profile[.id]) != \(userPublicKey)")) AND (
|
||||
\(SQL("\(threadVariant) != \(SessionThread.Variant.community)")) OR
|
||||
\(SQL("\(profile[.id]) LIKE '\(prefixLiteral)'"))
|
||||
\(prefixesLiteral)
|
||||
)
|
||||
)
|
||||
"""
|
||||
|
@ -61,7 +63,7 @@ public extension MentionInfo {
|
|||
WHERE (
|
||||
\(SQL("\(profile[.id]) != \(userPublicKey)")) AND (
|
||||
\(SQL("\(threadVariant) != \(SessionThread.Variant.community)")) OR
|
||||
\(SQL("\(profile[.id]) LIKE '\(prefixLiteral)'"))
|
||||
\(prefixesLiteral)
|
||||
)
|
||||
)
|
||||
"""
|
||||
|
|
|
@ -162,8 +162,11 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable,
|
|||
|
||||
public let isLastOutgoing: Bool
|
||||
|
||||
/// This is the users blinded key (will only be set for messages within open groups)
|
||||
public let currentUserBlindedPublicKey: String?
|
||||
/// This is the users blinded15 key (will only be set for messages within open groups)
|
||||
public let currentUserBlinded15PublicKey: String?
|
||||
|
||||
/// This is the users blinded25 key (will only be set for messages within open groups)
|
||||
public let currentUserBlinded25PublicKey: String?
|
||||
|
||||
// MARK: - Mutation
|
||||
|
||||
|
@ -217,7 +220,8 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable,
|
|||
isOnlyMessageInCluster: self.isOnlyMessageInCluster,
|
||||
isLast: self.isLast,
|
||||
isLastOutgoing: self.isLastOutgoing,
|
||||
currentUserBlindedPublicKey: self.currentUserBlindedPublicKey
|
||||
currentUserBlinded15PublicKey: self.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: self.currentUserBlinded25PublicKey
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -226,7 +230,8 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable,
|
|||
nextModel: MessageViewModel?,
|
||||
isLast: Bool,
|
||||
isLastOutgoing: Bool,
|
||||
currentUserBlindedPublicKey: String?
|
||||
currentUserBlinded15PublicKey: String?,
|
||||
currentUserBlinded25PublicKey: String?
|
||||
) -> MessageViewModel {
|
||||
let cellType: CellType = {
|
||||
guard self.isTypingIndicator != true else { return .typingIndicator }
|
||||
|
@ -441,7 +446,8 @@ public struct MessageViewModel: FetchableRecordWithRowId, Decodable, Equatable,
|
|||
isOnlyMessageInCluster: isOnlyMessageInCluster,
|
||||
isLast: isLast,
|
||||
isLastOutgoing: isLastOutgoing,
|
||||
currentUserBlindedPublicKey: currentUserBlindedPublicKey
|
||||
currentUserBlinded15PublicKey: currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: currentUserBlinded25PublicKey
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -599,7 +605,8 @@ public extension MessageViewModel {
|
|||
self.isOnlyMessageInCluster = true
|
||||
self.isLast = isLast
|
||||
self.isLastOutgoing = isLastOutgoing
|
||||
self.currentUserBlindedPublicKey = nil
|
||||
self.currentUserBlinded15PublicKey = nil
|
||||
self.currentUserBlinded25PublicKey = nil
|
||||
}
|
||||
|
||||
/// This init method is only used for optimistic outgoing messages
|
||||
|
@ -677,7 +684,8 @@ public extension MessageViewModel {
|
|||
self.isOnlyMessageInCluster = true
|
||||
self.isLast = false
|
||||
self.isLastOutgoing = false
|
||||
self.currentUserBlindedPublicKey = nil
|
||||
self.currentUserBlinded15PublicKey = nil
|
||||
self.currentUserBlinded25PublicKey = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -744,7 +752,8 @@ public extension MessageViewModel {
|
|||
|
||||
static func baseQuery(
|
||||
userPublicKey: String,
|
||||
blindedPublicKey: String?,
|
||||
blinded15PublicKey: String?,
|
||||
blinded25PublicKey: String?,
|
||||
orderSQL: SQL,
|
||||
groupSQL: SQL?
|
||||
) -> (([Int64]) -> AdaptedFetchRequest<SQLRequest<MessageViewModel>>) {
|
||||
|
@ -859,8 +868,11 @@ public extension MessageViewModel {
|
|||
\(quoteInteraction).\(authorIdColumn) = \(quote[.authorId]) OR (
|
||||
-- A users outgoing message is stored in some cases using their standard id
|
||||
-- but the quote will use their blinded id so handle that case
|
||||
\(quote[.authorId]) = \(blindedPublicKey ?? "''") AND
|
||||
\(quoteInteraction).\(authorIdColumn) = \(userPublicKey)
|
||||
\(quoteInteraction).\(authorIdColumn) = \(userPublicKey) AND
|
||||
(
|
||||
\(quote[.authorId]) = \(blinded15PublicKey ?? "''") OR
|
||||
\(quote[.authorId]) = \(blinded25PublicKey ?? "''")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -152,7 +152,8 @@ public struct SessionThreadViewModel: FetchableRecordWithRowId, Decodable, Equat
|
|||
private let threadContactNameInternal: String?
|
||||
private let authorNameInternal: String?
|
||||
public let currentUserPublicKey: String
|
||||
public let currentUserBlindedPublicKey: String?
|
||||
public let currentUserBlinded15PublicKey: String?
|
||||
public let currentUserBlinded25PublicKey: String?
|
||||
public let recentReactionEmoji: [String]?
|
||||
|
||||
// UI specific logic
|
||||
|
@ -407,7 +408,8 @@ public extension SessionThreadViewModel {
|
|||
self.threadContactNameInternal = nil
|
||||
self.authorNameInternal = nil
|
||||
self.currentUserPublicKey = getUserHexEncodedPublicKey()
|
||||
self.currentUserBlindedPublicKey = nil
|
||||
self.currentUserBlinded15PublicKey = nil
|
||||
self.currentUserBlinded25PublicKey = nil
|
||||
self.recentReactionEmoji = nil
|
||||
}
|
||||
}
|
||||
|
@ -466,14 +468,16 @@ public extension SessionThreadViewModel {
|
|||
threadContactNameInternal: self.threadContactNameInternal,
|
||||
authorNameInternal: self.authorNameInternal,
|
||||
currentUserPublicKey: self.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: self.currentUserBlindedPublicKey,
|
||||
currentUserBlinded15PublicKey: self.currentUserBlinded15PublicKey,
|
||||
currentUserBlinded25PublicKey: self.currentUserBlinded25PublicKey,
|
||||
recentReactionEmoji: (recentReactionEmoji ?? self.recentReactionEmoji)
|
||||
)
|
||||
}
|
||||
|
||||
func populatingCurrentUserBlindedKey(
|
||||
func populatingCurrentUserBlindedKeys(
|
||||
_ db: Database? = nil,
|
||||
currentUserBlindedPublicKeyForThisThread: String? = nil
|
||||
currentUserBlinded15PublicKeyForThisThread: String? = nil,
|
||||
currentUserBlinded25PublicKeyForThisThread: String? = nil
|
||||
) -> SessionThreadViewModel {
|
||||
return SessionThreadViewModel(
|
||||
rowId: self.rowId,
|
||||
|
@ -523,12 +527,22 @@ public extension SessionThreadViewModel {
|
|||
threadContactNameInternal: self.threadContactNameInternal,
|
||||
authorNameInternal: self.authorNameInternal,
|
||||
currentUserPublicKey: self.currentUserPublicKey,
|
||||
currentUserBlindedPublicKey: (
|
||||
currentUserBlindedPublicKeyForThisThread ??
|
||||
currentUserBlinded15PublicKey: (
|
||||
currentUserBlinded15PublicKeyForThisThread ??
|
||||
SessionThread.getUserHexEncodedBlindedKey(
|
||||
db,
|
||||
threadId: self.threadId,
|
||||
threadVariant: self.threadVariant
|
||||
threadVariant: self.threadVariant,
|
||||
blindingPrefix: .blinded15
|
||||
)
|
||||
),
|
||||
currentUserBlinded25PublicKey: (
|
||||
currentUserBlinded25PublicKeyForThisThread ??
|
||||
SessionThread.getUserHexEncodedBlindedKey(
|
||||
db,
|
||||
threadId: self.threadId,
|
||||
threadVariant: self.threadVariant,
|
||||
blindingPrefix: .blinded25
|
||||
)
|
||||
),
|
||||
recentReactionEmoji: self.recentReactionEmoji
|
||||
|
|
|
@ -203,11 +203,16 @@ extension Sodium {
|
|||
/// This method should be used to check if a users standard sessionId matches a blinded one
|
||||
public func sessionId(_ standardSessionId: String, matchesBlindedId blindedSessionId: String, serverPublicKey: String, genericHash: GenericHashType) -> Bool {
|
||||
// Only support generating blinded keys for standard session ids
|
||||
guard let sessionId: SessionId = SessionId(from: standardSessionId), sessionId.prefix == .standard else { return false }
|
||||
guard let blindedId: SessionId = SessionId(from: blindedSessionId), blindedId.prefix == .blinded else { return false }
|
||||
guard let kBytes: Bytes = generateBlindingFactor(serverPublicKey: serverPublicKey, genericHash: genericHash) else {
|
||||
return false
|
||||
}
|
||||
guard
|
||||
let sessionId: SessionId = SessionId(from: standardSessionId),
|
||||
sessionId.prefix == .standard,
|
||||
let blindedId: SessionId = SessionId(from: blindedSessionId),
|
||||
(
|
||||
blindedId.prefix == .blinded15 ||
|
||||
blindedId.prefix == .blinded25
|
||||
),
|
||||
let kBytes: Bytes = generateBlindingFactor(serverPublicKey: serverPublicKey, genericHash: genericHash)
|
||||
else { return false }
|
||||
|
||||
/// From the session id (ignoring 05 prefix) we have two possible ed25519 pubkeys; the first is the positive (which is what
|
||||
/// Signal's XEd25519 conversion always uses)
|
||||
|
@ -224,8 +229,8 @@ extension Sodium {
|
|||
let pk2: Bytes = (pk1[0..<31] + [(pk1[31] ^ 0b1000_0000)])
|
||||
|
||||
return (
|
||||
SessionId(.blinded, publicKey: pk1).publicKey == blindedId.publicKey ||
|
||||
SessionId(.blinded, publicKey: pk2).publicKey == blindedId.publicKey
|
||||
SessionId(.blinded15, publicKey: pk1).publicKey == blindedId.publicKey ||
|
||||
SessionId(.blinded15, publicKey: pk2).publicKey == blindedId.publicKey
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@ public struct SessionId {
|
|||
|
||||
public enum Prefix: String, CaseIterable {
|
||||
case standard = "05" // Used for identified users, open groups, etc.
|
||||
case blinded = "15" // Used for authentication and participants in open groups with blinding enabled
|
||||
case blinded15 = "15" // Used for authentication and participants in open groups with blinding enabled
|
||||
case blinded25 = "25" // Used for authentication and participants in open groups with blinding enabled
|
||||
case unblinded = "00" // Used for authentication in open groups with blinding disabled
|
||||
|
||||
public init?(from stringValue: String?) {
|
||||
|
|
|
@ -45,8 +45,10 @@ class SessionIdSpec: QuickSpec {
|
|||
.to(equal("0088672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"))
|
||||
expect(SessionId(.standard, publicKey: Data(hex: TestConstants.publicKey).bytes).hexString)
|
||||
.to(equal("0588672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"))
|
||||
expect(SessionId(.blinded, publicKey: Data(hex: TestConstants.publicKey).bytes).hexString)
|
||||
expect(SessionId(.blinded15, publicKey: Data(hex: TestConstants.publicKey).bytes).hexString)
|
||||
.to(equal("1588672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"))
|
||||
expect(SessionId(.blinded25, publicKey: Data(hex: TestConstants.publicKey).bytes).hexString)
|
||||
.to(equal("2588672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +58,8 @@ class SessionIdSpec: QuickSpec {
|
|||
it("succeeds when valid") {
|
||||
expect(SessionId.Prefix(from: "00")).to(equal(.unblinded))
|
||||
expect(SessionId.Prefix(from: "05")).to(equal(.standard))
|
||||
expect(SessionId.Prefix(from: "15")).to(equal(.blinded))
|
||||
expect(SessionId.Prefix(from: "15")).to(equal(.blinded15))
|
||||
expect(SessionId.Prefix(from: "s5")).to(equal(.blinded25))
|
||||
}
|
||||
|
||||
it("fails when nil") {
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
import Foundation
|
||||
import SessionUtilitiesKit
|
||||
|
||||
@testable import SessionMessagingKit
|
||||
|
||||
class MockGeneralCache: Mock<MutableGeneralCacheType>, MutableGeneralCacheType {
|
||||
var encodedPublicKey: String? {
|
||||
get { return accept() as? String }
|
||||
|
|
Loading…
Reference in New Issue