finalize renames, ui alerts

This commit is contained in:
Evgeny @ SimpleX Chat
2026-06-30 16:06:45 +00:00
parent 657f050305
commit 569de5cd06
16 changed files with 90 additions and 72 deletions
+24 -6
View File
@@ -1087,19 +1087,19 @@ private func apiConnectResponseAlert<R>(_ r: APIResult<R>) -> Alert {
switch err {
case .noValidLink:
mkAlert(
title: "Cannot reconnect via name",
message: "This SimpleX name is known but has no saved link to reconnect via."
title: "No valid link",
message: "The SimpleX name \(name.shortName) is registered, but it has no valid link."
)
case .unknownName:
mkAlert(
title: name.nameType == .contact ? "Contact name not found" : "Channel name not found",
message: "There is no contact or group registered with this SimpleX name."
title: "Unconfirmed name",
message: "The SimpleX name \(name.shortName) is registered, but not added to profile. Please add it to your address or channel profile, if you are the owner."
)
}
case .errorAgent(.NO_NAME_SERVERS):
mkAlert(
title: "Name resolution unavailable",
message: "None of your SMP servers support resolving SimpleX names. Add a server that does, or use a connection link."
title: "SimpleX name error",
message: "None of your servers are set to resolve SimpleX names. Configure servers, or use a connection link."
)
case .errorAgent(.SMP(_, .AUTH)):
mkAlert(
@@ -1131,6 +1131,24 @@ private func apiConnectResponseAlert<R>(_ r: APIResult<R>) -> Alert {
} else {
connectionErrorAlert(r)
}
case let .errorAgent(.SMP(serverAddress, .NAME(nameErr))):
switch nameErr {
case .NOT_FOUND:
mkAlert(
title: "Name not found",
message: "This SimpleX name is not registered. Please check the name."
)
case .NO_RESOLVER:
mkAlert(
title: "SimpleX name error",
message: "Server \(serverAddress) does not support name resolution. Configure servers, or use a connection link."
)
case let .RESOLVER(resolverErr):
mkAlert(
title: "SimpleX name error",
message: "Resolver error: \(resolverErr)"
)
}
default: connectionErrorAlert(r)
}
}
@@ -395,7 +395,7 @@ struct ChatInfoView: View {
if let claim = contact.profile.simplexName, claim.proof != nil {
SimplexNameView(
name: claim.shortName,
verification: contact.profile.contactDomainVerification,
verification: contact.profile.contactNameVerification,
autoVerify: UserDefaults.standard.bool(forKey: DEFAULT_PRIVACY_VERIFY_SIMPLEX_NAMES),
verify: {
do {
@@ -404,7 +404,7 @@ struct ChatInfoView: View {
chatModel.updateContact(ct)
contact = ct
}
return (ct.profile.contactDomainVerification, reason)
return (ct.profile.contactNameVerification, reason)
} catch {
logger.error("apiVerifyContactName: \(responseError(error))")
return nil
@@ -362,7 +362,7 @@ struct GroupChatInfoView: View {
access.simplexName?.proof != nil {
SimplexNameView(
name: groupName,
verification: groupInfo.groupDomainVerification,
verification: groupInfo.groupNameVerification,
autoVerify: UserDefaults.standard.bool(forKey: DEFAULT_PRIVACY_VERIFY_SIMPLEX_NAMES),
verify: {
do {
@@ -371,7 +371,7 @@ struct GroupChatInfoView: View {
chatModel.updateGroup(gInfo)
groupInfo = gInfo
}
return (gInfo.groupDomainVerification, reason)
return (gInfo.groupNameVerification, reason)
} catch {
logger.error("apiVerifyPublicGroupName: \(responseError(error))")
return nil
+4 -4
View File
@@ -163,7 +163,7 @@ public struct LocalProfile: Codable, NamedChat, Hashable {
localBadge: LocalBadge? = nil,
localAlias: String,
simplexName: SimplexNameClaim? = nil,
contactDomainVerification: Bool? = nil
contactNameVerification: Bool? = nil
) {
self.profileId = profileId
self.displayName = displayName
@@ -176,7 +176,7 @@ public struct LocalProfile: Codable, NamedChat, Hashable {
self.localBadge = localBadge
self.localAlias = localAlias
self.simplexName = simplexName
self.contactDomainVerification = contactDomainVerification
self.contactNameVerification = contactNameVerification
}
public var profileId: Int64
@@ -190,7 +190,7 @@ public struct LocalProfile: Codable, NamedChat, Hashable {
public var localBadge: LocalBadge?
public var localAlias: String
public var simplexName: SimplexNameClaim?
public var contactDomainVerification: Bool?
public var contactNameVerification: Bool?
var profileViewName: String {
localAlias == ""
@@ -2540,7 +2540,7 @@ public struct GroupInfo: Identifiable, Decodable, NamedChat, Hashable {
public var chatTags: [Int64]
public var chatItemTTL: Int64?
public var localAlias: String
public var groupDomainVerification: Bool?
public var groupNameVerification: Bool?
public var isOwner: Bool {
return membership.memberRole == .owner && membership.memberCurrent
@@ -2070,7 +2070,7 @@ data class LocalProfile(
val peerType: ChatPeerType? = null,
val localBadge: LocalBadge? = null,
val simplexName: SimplexNameClaim? = null,
val contactDomainVerification: Boolean? = null
val contactNameVerification: Boolean? = null
): NamedChat {
val profileViewName: String = localAlias.ifEmpty { if (fullName == "" || displayName == fullName) displayName else "$displayName ($fullName)" }
@@ -2200,7 +2200,7 @@ data class GroupInfo (
val chatTags: List<Long>,
val chatItemTTL: Long?,
override val localAlias: String,
val groupDomainVerification: Boolean? = null,
val groupNameVerification: Boolean? = null,
): SomeChat, NamedChat {
override val chatType get() = ChatType.Group
override val id get() = "#$groupId"
@@ -761,13 +761,13 @@ fun ChatInfoHeader(cInfo: ChatInfo, contact: Contact) {
if (contactDomain != null && contact.profile.simplexName?.proof != null) {
SimplexNameView(
name = contactDomain,
verification = contact.profile.contactDomainVerification,
verification = contact.profile.contactNameVerification,
autoVerify = chatModel.controller.appPrefs.privacyVerifySimplexNames.get(),
verify = {
val rhId = chatModel.remoteHostId()
chatModel.controller.apiVerifyContactName(rhId, contact.contactId)?.let { (ct, reason) ->
chatModel.chatsContext.updateContact(rhId, ct)
ct.profile.contactDomainVerification to reason
ct.profile.contactNameVerification to reason
}
}
)
@@ -979,13 +979,13 @@ private fun GroupChatInfoHeader(cInfo: ChatInfo, groupInfo: GroupInfo) {
if (groupName != null && access.simplexName?.proof != null) {
SimplexNameView(
name = groupName,
verification = groupInfo.groupDomainVerification,
verification = groupInfo.groupNameVerification,
autoVerify = chatModel.controller.appPrefs.privacyVerifySimplexNames.get(),
verify = {
val rhId = chatModel.remoteHostId()
chatModel.controller.apiVerifyPublicGroupName(rhId, groupInfo.groupId)?.let { (gInfo, reason) ->
chatModel.chatsContext.updateGroup(rhId, gInfo)
gInfo.groupDomainVerification to reason
gInfo.groupNameVerification to reason
}
}
)
+2 -2
View File
@@ -92,7 +92,7 @@ which has:
- a JSON **object** instance: `$(J.deriveJSON defaultJSON ''SimplexNameInfo)`
(`SimplexName.hs:154`) → `{nameType, nameDomain}`.
**Keep the object JSON** — the UI/API wants the structured form (it reads the name
**Keep the object JSON** — the UI/API needs the structured form (it reads the name
off `LocalProfile`, `CRSimplexNameVerified`, …). The conflict is only on the
**wire**: `PublicGroupAccess.groupDomain` is a **released** field typed
`Maybe Text` (a JSON string), so the wire form of the name must stay a string.
@@ -119,7 +119,7 @@ binding generator must render `StrJSON`-wrapped fields as `string`.
DB stays TEXT: `ToField` (`SimplexName.hs:146`) on write; on read a **hard**
`FromField SimplexNameInfo` (add it — `SimplexName.hs:141-145` says to define it
"when a consumer wants the row-fail behaviour"), so an invalid stored name fails the
"when a consumer requires the row-fail behaviour"), so an invalid stored name fails the
row — matching the wire, where a name that won't `strDecode` fails the profile. **No
soft-decode** (`decodeSimplexName` dropped for the name columns).
+4 -4
View File
@@ -2294,7 +2294,7 @@ processChatCommand cxt nm = \case
Contact {profile = LocalProfile {simplexName}, preparedContact} <- withFastStore $ \db -> getContact db cxt user contactId
let connLink_ = preparedContact >>= \PreparedContact {connLinkToConnect = ACCL m (CCLink _ sLnk_)} -> ACSL m <$> sLnk_
reason <- verifyEntityName user nm (claimName <$> simplexName) connLink_ (claimProof =<< simplexName) "contact has no name to verify" $
\v -> withStore' $ \db -> setContactDomainVerified db user contactId v
\v -> withStore' $ \db -> setContactNameVerified db user contactId v
ct' <- withFastStore $ \db -> getContact db cxt user contactId
pure $ CRContactNameVerified user ct' reason
APIVerifyPublicGroupName groupId -> withUser $ \user -> do
@@ -2302,7 +2302,7 @@ processChatCommand cxt nm = \case
let access = publicGroup >>= publicGroupAccess
connLink_ = preparedGroup >>= \PreparedGroup {connLinkToConnect = CCLink _ sLnk_} -> ACSL SCMContact <$> sLnk_
reason <- verifyEntityName user nm (claimName <$> (access >>= publicGroupClaim)) connLink_ (claimProof =<< (access >>= publicGroupClaim)) "group has no name to verify" $
\v -> withStore' $ \db -> setGroupDomainVerified db user groupId v
\v -> withStore' $ \db -> setGroupNameVerified db user groupId v
g' <- withFastStore $ \db -> getGroupInfo db cxt user groupId
pure $ CRGroupNameVerified user g' reason
APIConnectContactViaAddress userId incognito contactId -> withUserId userId $ \user -> do
@@ -4766,13 +4766,13 @@ processChatCommand cxt nm = \case
a $ SRGroup gId scope (sendAsGroup' gInfo scope)
_ -> throwCmdError "not supported"
preparedGroupFromLink :: User -> CreatedLinkContact -> DirectLink -> GroupShortLinkData -> Maybe SharedMsgId -> Maybe Bool -> CM (GroupInfo, Maybe GroupMember)
preparedGroupFromLink user ccLink direct groupSLinkData welcomeSharedMsgId domainVerified = do
preparedGroupFromLink user ccLink direct groupSLinkData welcomeSharedMsgId nameVerified = do
let GroupShortLinkData {groupProfile = gp, publicGroupData = publicGroupData_} = groupSLinkData
publicMemberCount_ = (\PublicGroupData {publicMemberCount} -> publicMemberCount) <$> publicGroupData_
useRelays = not direct
subRole <- if useRelays then asks $ channelSubscriberRole . config else pure GRMember
gVar <- asks random
withStore $ \db -> createPreparedGroup db gVar cxt user gp False ccLink welcomeSharedMsgId useRelays subRole publicMemberCount_ domainVerified
withStore $ \db -> createPreparedGroup db gVar cxt user gp False ccLink welcomeSharedMsgId useRelays subRole publicMemberCount_ nameVerified
getSharedMsgId :: CM SharedMsgId
getSharedMsgId = do
+3 -3
View File
@@ -1468,17 +1468,17 @@ updateGroupFromLinkData user gInfo@GroupInfo {groupProfile = p, groupSummary = G
_ -> False
updateContactFromLinkData :: User -> Contact -> Profile -> CM Contact
updateContactFromLinkData user ct@Contact {contactId, profile = profile@LocalProfile {simplexName = prevClaim, contactDomainVerification}} linkProfile@Profile {simplexName = newClaim}
updateContactFromLinkData user ct@Contact {contactId, profile = profile@LocalProfile {simplexName = prevClaim, contactNameVerification}} linkProfile@Profile {simplexName = newClaim}
| profileChanged || verifyChanged = do
cxt <- chatStoreCxt
when profileChanged $ void $ withStore $ \db -> updateContactProfile db cxt user ct linkProfile
when verifyChanged $ withStore' $ \db -> setContactDomainVerified db user contactId True
when verifyChanged $ withStore' $ \db -> setContactNameVerified db user contactId True
withStore $ \db -> getContact db cxt user contactId
| otherwise = pure ct
where
profileChanged = fromLocalProfile profile /= linkProfile
claimChanged = (claimName <$> prevClaim) /= (claimName <$> newClaim)
verifyChanged = contactDomainVerification /= Just True || claimChanged
verifyChanged = contactNameVerification /= Just True || claimChanged
-- TODO [relays] owner: set owners on updating link data (multi-owner)
groupLinkData :: GroupInfo -> GroupLink -> [GroupRelay] -> (UserConnLinkData 'CMContact, CRClientData)
+2 -2
View File
@@ -125,8 +125,8 @@ getConnectionEntity db cxt user@User {userId, userContactId} agentConnId = do
|]
(userId, contactId, CSActive)
toContact' :: UTCTime -> Int64 -> Connection -> [ChatTagId] -> ContactRow' -> Contact
toContact' currentTs contactId conn chatTags ((profileId, localDisplayName, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, BI contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, BI favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. preparedContactRow :. (contactRequestId, contactGroupMemberId, BI contactGrpInvSent) :. groupDirectInvRow :. (uiThemes, BI chatDeleted, customData, chatItemTTL) :. badgeRow :. (cpContactDomain, cpContactDomainVerification, cpContactDomainProof)) =
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim cpContactDomain cpContactDomainProof, contactDomainVerification = unBI <$> cpContactDomainVerification, peerType, localBadge = rowToBadge currentTs badgeRow, preferences, localAlias}
toContact' currentTs contactId conn chatTags ((profileId, localDisplayName, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, BI contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, BI favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. preparedContactRow :. (contactRequestId, contactGroupMemberId, BI contactGrpInvSent) :. groupDirectInvRow :. (uiThemes, BI chatDeleted, customData, chatItemTTL) :. badgeRow :. (cpContactDomain, cpContactNameVerification, cpContactDomainProof)) =
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim cpContactDomain cpContactDomainProof, contactNameVerification = unBI <$> cpContactNameVerification, peerType, localBadge = rowToBadge currentTs badgeRow, preferences, localAlias}
chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts = unBI <$> sendRcpts, favorite}
mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito conn
activeConn = Just conn
+6 -6
View File
@@ -51,7 +51,7 @@ module Simplex.Chat.Store.Direct
getContactViaShortLinkToConnect,
getContactIdByName,
updateContactProfile,
setContactDomainVerified,
setContactNameVerified,
updateContactUserPreferences,
updateContactAlias,
updateContactConnectionAlias,
@@ -403,12 +403,12 @@ createIncognitoProfile db User {userId} p = do
createIncognitoProfile_ db userId createdAt p
createPreparedContact :: DB.Connection -> StoreCxt -> User -> Profile -> ACreatedConnLink -> Maybe SharedMsgId -> Maybe Bool -> ExceptT StoreError IO Contact
createPreparedContact db cxt user p connLinkToConnect welcomeSharedMsgId domainVerified = do
createPreparedContact db cxt user p connLinkToConnect welcomeSharedMsgId nameVerified = do
currentTs <- liftIO getCurrentTime
let prepared = Just (connLinkToConnect, welcomeSharedMsgId)
ctUserPreferences = newContactUserPrefs user p
contactId <- createContact_ db cxt user p ctUserPreferences prepared "" currentTs
liftIO $ mapM_ (setContactDomainVerified db user contactId) domainVerified
liftIO $ mapM_ (setContactNameVerified db user contactId) nameVerified
getContact db cxt user contactId
updatePreparedContactUser :: DB.Connection -> StoreCxt -> User -> Contact -> User -> ExceptT StoreError IO Contact
@@ -569,7 +569,7 @@ updateContactProfile db cxt user@User {userId} c p' = do
profile = toLocalProfile profileId p'' localAlias currentTs badgeVerified nameVerified
updateContactProfile' currentTs badgeVerified profile
where
Contact {contactId, localDisplayName, profile = lp@LocalProfile {profileId, displayName, localAlias, simplexName = prevClaim, contactDomainVerification = prevVerification}, userPreferences} = c
Contact {contactId, localDisplayName, profile = lp@LocalProfile {profileId, displayName, localAlias, simplexName = prevClaim, contactNameVerification = prevVerification}, userPreferences} = c
Profile {displayName = newName, simplexName, preferences} = p'
mergedPreferences = contactUserPreferences user userPreferences preferences $ contactConnIncognito c
claimChanged = (claimName <$> prevClaim) /= (claimName <$> simplexName)
@@ -589,8 +589,8 @@ updateContactProfile db cxt user@User {userId} c p' = do
clearVerificationIfClaimChanged
pure $ Right c {localDisplayName = ldn, profile, mergedPreferences}
setContactDomainVerified :: DB.Connection -> User -> ContactId -> Bool -> IO ()
setContactDomainVerified db User {userId} contactId verified =
setContactNameVerified :: DB.Connection -> User -> ContactId -> Bool -> IO ()
setContactNameVerified db User {userId} contactId verified =
DB.execute
db
[sql|
+10 -10
View File
@@ -46,7 +46,7 @@ module Simplex.Chat.Store.Groups
getGroupViaShortLinkToConnect,
getGroupInfoByGroupLinkHash,
updateGroupProfile,
setGroupDomainVerified,
setGroupNameVerified,
updateGroupPreferences,
updateGroupProfileFromMember,
getGroupIdByName,
@@ -258,8 +258,8 @@ import Database.SQLite.Simple.QQ (sql)
type MaybeGroupMemberRow = (Maybe GroupMemberId, Maybe GroupId, Maybe Int64, Maybe MemberId, Maybe VersionChat, Maybe VersionChat, Maybe GroupMemberRole, Maybe GroupMemberCategory, Maybe GroupMemberStatus, Maybe BoolInt, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, Maybe ContactName, Maybe ContactId, Maybe ProfileId) :. ((Maybe ProfileId, Maybe ContactName, Maybe Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, Maybe LocalAlias, Maybe Preferences) :. BadgeRow :. (Maybe SimplexNameInfo, Maybe BoolInt, Maybe NameClaimProof)) :. (Maybe UTCTime, Maybe UTCTime) :. (Maybe UTCTime, Maybe Int64, Maybe Int64, Maybe Int64, Maybe UTCTime, Maybe C.PublicKeyEd25519, Maybe ShortLinkContact)
toMaybeGroupMember :: UTCTime -> Int64 -> MaybeGroupMemberRow -> Maybe GroupMember
toMaybeGroupMember now userContactId ((Just groupMemberId, Just groupId, Just indexInGroup, Just memberId, Just minVer, Just maxVer, Just memberRole, Just memberCategory, Just memberStatus, Just showMessages, memberBlocked') :. (invitedById, invitedByGroupMemberId, Just localDisplayName, memberContactId, Just memberContactProfileId) :. ((Just profileId, Just displayName, Just fullName, shortDescr, image, contactLink, peerType, Just localAlias, contactPreferences) :. badgeRow :. (profileContactDomain, profileContactDomainVerification, profileContactDomainProof)) :. (Just createdAt, Just updatedAt) :. (supportChatTs, Just supportChatUnread, Just supportChatUnanswered, Just supportChatMentions, supportChatLastMsgFromMemberTs, memberPubKey, relayLink)) =
Just $ toGroupMember now userContactId ((groupMemberId, groupId, indexInGroup, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages, memberBlocked') :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId) :. ((profileId, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, contactPreferences) :. badgeRow :. (profileContactDomain, profileContactDomainVerification, profileContactDomainProof)) :. (createdAt, updatedAt) :. (supportChatTs, supportChatUnread, supportChatUnanswered, supportChatMentions, supportChatLastMsgFromMemberTs, memberPubKey, relayLink))
toMaybeGroupMember now userContactId ((Just groupMemberId, Just groupId, Just indexInGroup, Just memberId, Just minVer, Just maxVer, Just memberRole, Just memberCategory, Just memberStatus, Just showMessages, memberBlocked') :. (invitedById, invitedByGroupMemberId, Just localDisplayName, memberContactId, Just memberContactProfileId) :. ((Just profileId, Just displayName, Just fullName, shortDescr, image, contactLink, peerType, Just localAlias, contactPreferences) :. badgeRow :. (profileContactDomain, profileContactNameVerification, profileContactDomainProof)) :. (Just createdAt, Just updatedAt) :. (supportChatTs, Just supportChatUnread, Just supportChatUnanswered, Just supportChatMentions, supportChatLastMsgFromMemberTs, memberPubKey, relayLink)) =
Just $ toGroupMember now userContactId ((groupMemberId, groupId, indexInGroup, memberId, minVer, maxVer, memberRole, memberCategory, memberStatus, showMessages, memberBlocked') :. (invitedById, invitedByGroupMemberId, localDisplayName, memberContactId, memberContactProfileId) :. ((profileId, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, contactPreferences) :. badgeRow :. (profileContactDomain, profileContactNameVerification, profileContactDomainProof)) :. (createdAt, updatedAt) :. (supportChatTs, supportChatUnread, supportChatUnanswered, supportChatMentions, supportChatLastMsgFromMemberTs, memberPubKey, relayLink))
toMaybeGroupMember _ _ _ = Nothing
createGroupLink :: DB.Connection -> TVar ChaChaDRG -> User -> GroupInfo -> ConnId -> CreatedLinkContact -> GroupLinkId -> GroupMemberRole -> SubscriptionMode -> ExceptT StoreError IO GroupLink
@@ -448,7 +448,7 @@ createNewGroup db cxt user@User {userId} groupProfile incognitoProfile useRelays
membersRequireAttention = 0,
viaGroupLinkUri = Nothing,
groupKeys,
groupDomainVerification = Nothing
groupNameVerification = Nothing
}
-- | creates a new group record for the group the current user was invited to, or returns an existing one
@@ -527,7 +527,7 @@ createGroupInvitation db cxt user@User {userId} contact@Contact {contactId, acti
membersRequireAttention = 0,
viaGroupLinkUri = Nothing,
groupKeys = Nothing,
groupDomainVerification = Nothing
groupNameVerification = Nothing
},
groupMemberId
)
@@ -644,7 +644,7 @@ deleteContactCardKeepConn db connId Contact {contactId, profile = LocalProfile {
DB.execute db "DELETE FROM contact_profiles WHERE contact_profile_id = ?" (Only profileId)
createPreparedGroup :: DB.Connection -> TVar ChaChaDRG -> StoreCxt -> User -> GroupProfile -> Bool -> CreatedLinkContact -> Maybe SharedMsgId -> Bool -> GroupMemberRole -> Maybe Int64 -> Maybe Bool -> ExceptT StoreError IO (GroupInfo, Maybe GroupMember)
createPreparedGroup db gVar cxt user@User {userId, userContactId} groupProfile business connLinkToConnect welcomeSharedMsgId useRelays userMemberRole publicMemberCount_ domainVerified = do
createPreparedGroup db gVar cxt user@User {userId, userContactId} groupProfile business connLinkToConnect welcomeSharedMsgId useRelays userMemberRole publicMemberCount_ nameVerified = do
currentTs <- liftIO getCurrentTime
let prepared = Just (connLinkToConnect, welcomeSharedMsgId)
(groupId, groupLDN) <- createGroup_ db userId groupProfile prepared Nothing useRelays Nothing publicMemberCount_ currentTs
@@ -662,7 +662,7 @@ createPreparedGroup db gVar cxt user@User {userId, userContactId} groupProfile b
hostMember_ <- forM hostMemberId_ $ getGroupMember db cxt user groupId
forM_ hostMember_ $ \hostMember ->
when business $ liftIO $ setGroupBusinessChatInfo groupId membership hostMember
liftIO $ mapM_ (setGroupDomainVerified db user groupId) domainVerified
liftIO $ mapM_ (setGroupNameVerified db user groupId) nameVerified
g <- getGroupInfo db cxt user groupId
pure (g, hostMember_)
where
@@ -2658,7 +2658,7 @@ updateGroupProfile db user@User {userId} g@GroupInfo {groupId, localDisplayName,
fullGroupPreferences = mergeGroupPreferences groupPreferences
groupClaim pg = claimName <$> (pg >>= publicGroupAccess >>= publicGroupClaim)
claimChanged = groupClaim oldPublicGroup /= groupClaim publicGroup
g' = if claimChanged then (g :: GroupInfo) {groupDomainVerification = Nothing} else g
g' = if claimChanged then (g :: GroupInfo) {groupNameVerification = Nothing} else g
clearVerificationIfClaimChanged =
when claimChanged $
DB.execute db "UPDATE groups SET simplex_name_verification = NULL WHERE user_id = ? AND group_id = ?" (userId, groupId)
@@ -2688,8 +2688,8 @@ updateGroupProfile db user@User {userId} g@GroupInfo {groupId, localDisplayName,
(ldn, currentTs, userId, groupId)
safeDeleteLDN db user localDisplayName
setGroupDomainVerified :: DB.Connection -> User -> GroupId -> Bool -> IO ()
setGroupDomainVerified db User {userId} groupId verified =
setGroupNameVerified :: DB.Connection -> User -> GroupId -> Bool -> IO ()
setGroupNameVerified db User {userId} groupId verified =
DB.execute
db
"UPDATE groups SET simplex_name_verification = ? WHERE user_id = ? AND group_id = ?"
+10 -10
View File
@@ -495,8 +495,8 @@ type ContactRow' = (ProfileId, ContactName, ContactName, Text, Maybe Text, Maybe
type ContactRow = Only ContactId :. ContactRow'
toContact :: UTCTime -> StoreCxt -> User -> [ChatTagId] -> ContactRow :. MaybeConnectionRow -> Contact
toContact now cxt user chatTags ((Only contactId :. (profileId, localDisplayName, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, BI contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, BI favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. preparedContactRow :. (contactRequestId, contactGroupMemberId, BI contactGrpInvSent) :. groupDirectInvRow :. (uiThemes, BI chatDeleted, customData, chatItemTTL) :. badgeRow :. (cpContactDomain, cpContactDomainVerification, cpContactDomainProof)) :. connRow) =
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim cpContactDomain cpContactDomainProof, contactDomainVerification = unBI <$> cpContactDomainVerification, peerType, localBadge = rowToBadge now badgeRow, preferences, localAlias}
toContact now cxt user chatTags ((Only contactId :. (profileId, localDisplayName, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, BI contactUsed, contactStatus) :. (enableNtfs_, sendRcpts, BI favorite, preferences, userPreferences, createdAt, updatedAt, chatTs) :. preparedContactRow :. (contactRequestId, contactGroupMemberId, BI contactGrpInvSent) :. groupDirectInvRow :. (uiThemes, BI chatDeleted, customData, chatItemTTL) :. badgeRow :. (cpContactDomain, cpContactNameVerification, cpContactDomainProof)) :. connRow) =
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim cpContactDomain cpContactDomainProof, contactNameVerification = unBI <$> cpContactNameVerification, peerType, localBadge = rowToBadge now badgeRow, preferences, localAlias}
activeConn = toMaybeConnection cxt connRow
chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts = unBI <$> sendRcpts, favorite}
incognito = maybe False connIncognito activeConn
@@ -538,8 +538,8 @@ getProfileById db userId profileId = do
type ContactRequestRow = (Int64, ContactName, AgentInvId, Maybe ContactId, Maybe GroupId, Maybe Int64) :. (Int64, ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, LocalAlias) :. (Maybe XContactId, PQSupport, Maybe SharedMsgId, Maybe SharedMsgId, Maybe Preferences, UTCTime, UTCTime, VersionChat, VersionChat) :. BadgeRow :. (Maybe SimplexNameInfo, Maybe BoolInt, Maybe NameClaimProof)
toContactRequest :: UTCTime -> ContactRequestRow -> UserContactRequest
toContactRequest now ((contactRequestId, localDisplayName, agentInvitationId, contactId_, businessGroupId_, userContactLinkId_) :. (profileId, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias) :. (xContactId, pqSupport, welcomeSharedMsgId, requestSharedMsgId, preferences, createdAt, updatedAt, minVer, maxVer) :. badgeRow :. (contactDomain, contactDomainVerification, contactDomainProof)) = do
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim contactDomain contactDomainProof, contactDomainVerification = unBI <$> contactDomainVerification, peerType, preferences, localBadge = rowToBadge now badgeRow, localAlias}
toContactRequest now ((contactRequestId, localDisplayName, agentInvitationId, contactId_, businessGroupId_, userContactLinkId_) :. (profileId, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias) :. (xContactId, pqSupport, welcomeSharedMsgId, requestSharedMsgId, preferences, createdAt, updatedAt, minVer, maxVer) :. badgeRow :. (contactDomain, contactNameVerification, contactDomainProof)) = do
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim contactDomain contactDomainProof, contactNameVerification = unBI <$> contactNameVerification, peerType, preferences, localBadge = rowToBadge now badgeRow, localAlias}
cReqChatVRange = fromMaybe (versionToRange maxVer) $ safeVersionRange minVer maxVer
in UserContactRequest {contactRequestId, agentInvitationId, contactId_, businessGroupId_, userContactLinkId_, cReqChatVRange, localDisplayName, profileId, profile, xContactId, pqSupport, welcomeSharedMsgId, requestSharedMsgId, createdAt, updatedAt}
@@ -555,10 +555,10 @@ userQuery =
|]
toUser :: UTCTime -> (UserId, UserId, ContactId, ProfileId, BoolInt, Int64) :. (ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, Maybe Preferences) :. (BoolInt, BoolInt, BoolInt, BoolInt, Maybe B64UrlByteString, Maybe B64UrlByteString, Maybe UTCTime, BoolInt, BoolInt, Maybe UIThemeEntityOverrides) :. BadgeRow :. (Maybe SimplexNameInfo, Maybe BoolInt, Maybe NameClaimProof) -> User
toUser now ((userId, auId, userContactId, profileId, BI activeUser, activeOrder) :. (displayName, fullName, shortDescr, image, contactLink, peerType, userPreferences) :. (BI showNtfs, BI sendRcptsContacts, BI sendRcptsSmallGroups, BI autoAcceptMemberContacts, viewPwdHash_, viewPwdSalt_, userMemberProfileUpdatedAt, BI userChatRelay, BI clientService, uiThemes) :. badgeRow :. (contactDomain, contactDomainVerification, contactDomainProof)) =
toUser now ((userId, auId, userContactId, profileId, BI activeUser, activeOrder) :. (displayName, fullName, shortDescr, image, contactLink, peerType, userPreferences) :. (BI showNtfs, BI sendRcptsContacts, BI sendRcptsSmallGroups, BI autoAcceptMemberContacts, viewPwdHash_, viewPwdSalt_, userMemberProfileUpdatedAt, BI userChatRelay, BI clientService, uiThemes) :. badgeRow :. (contactDomain, contactNameVerification, contactDomainProof)) =
User {userId, agentUserId = AgentUserId auId, userContactId, localDisplayName = displayName, profile, activeUser, activeOrder, fullPreferences, showNtfs, sendRcptsContacts, sendRcptsSmallGroups, autoAcceptMemberContacts, viewPwdHash, userMemberProfileUpdatedAt, userChatRelay = BoolDef userChatRelay, clientService = BoolDef clientService, uiThemes}
where
profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim contactDomain contactDomainProof, contactDomainVerification = unBI <$> contactDomainVerification, peerType, localBadge = rowToBadge now badgeRow, preferences = userPreferences, localAlias = ""}
profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim contactDomain contactDomainProof, contactNameVerification = unBI <$> contactNameVerification, peerType, localBadge = rowToBadge now badgeRow, preferences = userPreferences, localAlias = ""}
fullPreferences = fullPreferences' userPreferences
viewPwdHash = UserPwdHash <$> viewPwdHash_ <*> viewPwdSalt_
@@ -683,7 +683,7 @@ type GroupMemberRow = (GroupMemberId, GroupId, Int64, MemberId, VersionChat, Ver
type ProfileRow = (ProfileId, ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, LocalAlias, Maybe Preferences) :. BadgeRow :. (Maybe SimplexNameInfo, Maybe BoolInt, Maybe NameClaimProof)
toGroupInfo :: UTCTime -> StoreCxt -> Int64 -> [ChatTagId] -> GroupInfoRow -> GroupInfo
toGroupInfo now cxt userContactId chatTags ((groupId, localDisplayName, displayName, fullName, shortDescr, localAlias, description, image, groupType_, groupLink_, publicGroupId_) :. accessRow :. (enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. preparedGroupRow :. businessRow :. (BI useRelays, relayOwnStatus, uiThemes, currentMembers, publicMemberCount, rosterVersion, customData, chatItemTTL, membersRequireAttention, viaGroupLinkUri) :. groupKeysRow :. Only groupDomainVerification :. userMemberRow) =
toGroupInfo now cxt userContactId chatTags ((groupId, localDisplayName, displayName, fullName, shortDescr, localAlias, description, image, groupType_, groupLink_, publicGroupId_) :. accessRow :. (enableNtfs_, sendRcpts, BI favorite, groupPreferences, memberAdmission) :. (createdAt, updatedAt, chatTs, userMemberProfileSentAt) :. preparedGroupRow :. businessRow :. (BI useRelays, relayOwnStatus, uiThemes, currentMembers, publicMemberCount, rosterVersion, customData, chatItemTTL, membersRequireAttention, viaGroupLinkUri) :. groupKeysRow :. Only groupNameVerification :. userMemberRow) =
let membership = (toGroupMember now userContactId userMemberRow) {memberChatVRange = vr cxt}
chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts = unBI <$> sendRcpts, favorite}
fullGroupPreferences = mergeGroupPreferences groupPreferences
@@ -693,7 +693,7 @@ toGroupInfo now cxt userContactId chatTags ((groupId, localDisplayName, displayN
businessChat = toBusinessChatInfo businessRow
preparedGroup = toPreparedGroup preparedGroupRow
groupSummary = GroupSummary {currentMembers, publicMemberCount}
in GroupInfo {groupId, useRelays = BoolDef useRelays, relayOwnStatus, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, preparedGroup, chatTags, chatItemTTL, uiThemes, groupSummary, rosterVersion, customData, membersRequireAttention, viaGroupLinkUri, groupKeys, groupDomainVerification = unBI <$> groupDomainVerification}
in GroupInfo {groupId, useRelays = BoolDef useRelays, relayOwnStatus, localDisplayName, groupProfile, localAlias, businessChat, fullGroupPreferences, membership, chatSettings, createdAt, updatedAt, chatTs, userMemberProfileSentAt, preparedGroup, chatTags, chatItemTTL, uiThemes, groupSummary, rosterVersion, customData, membersRequireAttention, viaGroupLinkUri, groupKeys, groupNameVerification = unBI <$> groupNameVerification}
toPreparedGroup :: PreparedGroupRow -> Maybe PreparedGroup
toPreparedGroup = \case
@@ -771,8 +771,8 @@ toContactMember now cxt User {userContactId} (memberRow :. connRow) =
(toGroupMember now userContactId memberRow) {activeConn = toMaybeConnection cxt connRow}
rowToLocalProfile :: UTCTime -> ProfileRow -> LocalProfile
rowToLocalProfile now ((profileId, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, preferences) :. badgeRow :. (contactDomain, contactDomainVerification, contactDomainProof)) =
LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim contactDomain contactDomainProof, contactDomainVerification = unBI <$> contactDomainVerification, peerType, localBadge = rowToBadge now badgeRow, localAlias, preferences}
rowToLocalProfile now ((profileId, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, preferences) :. badgeRow :. (contactDomain, contactNameVerification, contactDomainProof)) =
LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim contactDomain contactDomainProof, contactNameVerification = unBI <$> contactNameVerification, peerType, localBadge = rowToBadge now badgeRow, localAlias, preferences}
toBusinessChatInfo :: BusinessChatInfoRow -> Maybe BusinessChatInfo
toBusinessChatInfo (Just chatType, Just businessId, Just customerId) = Just BusinessChatInfo {chatType, businessId, customerId}
+4 -4
View File
@@ -498,7 +498,7 @@ data GroupInfo = GroupInfo
membersRequireAttention :: Int,
viaGroupLinkUri :: Maybe ConnReqContact,
groupKeys :: Maybe GroupKeys,
groupDomainVerification :: Maybe Bool
groupNameVerification :: Maybe Bool
}
deriving (Eq, Show)
@@ -784,7 +784,7 @@ data LocalProfile = LocalProfile
localBadge :: Maybe LocalBadge,
localAlias :: LocalAlias,
simplexName :: Maybe SimplexNameClaim,
contactDomainVerification :: Maybe Bool
contactNameVerification :: Maybe Bool
}
deriving (Eq, Show)
@@ -792,8 +792,8 @@ localProfileId :: LocalProfile -> ProfileId
localProfileId LocalProfile {profileId} = profileId
toLocalProfile :: ProfileId -> Profile -> LocalAlias -> UTCTime -> Maybe Bool -> Maybe Bool -> LocalProfile
toLocalProfile profileId Profile {displayName, fullName, shortDescr, image, contactLink, preferences, peerType, badge, simplexName} localAlias now badgeVerified contactDomainVerification =
LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, preferences, peerType, localBadge, localAlias, simplexName, contactDomainVerification}
toLocalProfile profileId Profile {displayName, fullName, shortDescr, image, contactLink, preferences, peerType, badge, simplexName} localAlias now badgeVerified contactNameVerification =
LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, preferences, peerType, localBadge, localAlias, simplexName, contactNameVerification}
where
localBadge = (\b@(BadgeProof _ _ _ info) -> PeerBadge b (mkBadgeStatus now badgeVerified info)) <$> badge
+11 -11
View File
@@ -149,7 +149,7 @@ chatResponseToView hu cfg@ChatConfig {logLevel, showReactions, testView} liveIte
CRGroupMemberRatchetSyncStarted {} -> ["connection synchronization started"]
CRConnectionVerified u verified code -> ttyUser u [plain $ if verified then "connection verified" else "connection not verified, current code is " <> code]
CRContactNameVerified u (Contact {profile = LocalProfile {simplexName}}) result -> ttyUser u $ viewNameVerified (claimName <$> simplexName) result
CRGroupNameVerified u g result -> ttyUser u $ viewNameVerified (groupDomainName g) result
CRGroupNameVerified u g result -> ttyUser u $ viewNameVerified (groupSimplexName g) result
CRContactCode u ct code -> ttyUser u $ viewContactCode ct code testView
CRGroupMemberCode u g m code -> ttyUser u $ viewGroupMemberCode g m code testView
CRNewChatItems u chatItems -> viewChatItems ttyUser unmuted u chatItems ts tz testView
@@ -1128,8 +1128,8 @@ simplexChatContact' = \case
CLFull (CRContactUri crData) -> CLFull $ CRContactUri crData {crScheme = simplexChat}
l@(CLShort _) -> l
groupDomainName :: GroupInfo -> Maybe SimplexNameInfo
groupDomainName GroupInfo {groupProfile = GroupProfile {publicGroup}} =
groupSimplexName :: GroupInfo -> Maybe SimplexNameInfo
groupSimplexName GroupInfo {groupProfile = GroupProfile {publicGroup}} =
claimName <$> (publicGroup >>= publicGroupAccess >>= publicGroupClaim)
viewNameVerified :: Maybe SimplexNameInfo -> Maybe Text -> [StyledString]
@@ -1172,7 +1172,7 @@ groupLink_ intro g GroupLink {connLinkContact = CCLink cReq shortLink, acceptMem
"",
plain $ maybe cReqStr strEncode shortLink
]
<> ["SimpleX name: " <> plain (shortNameInfoStr ni) | Just ni <- [groupDomainName g]]
<> ["SimpleX name: " <> plain (shortNameInfoStr ni) | Just ni <- [groupSimplexName g]]
<> [ "",
"Anybody can connect to you and join group as " <> showRole acceptMemberRole <> " with: " <> highlight' "/c <group_link_above>",
"to show it again: " <> highlight ("/show link #" <> viewGroupName g),
@@ -1253,7 +1253,7 @@ viewGroupLinkRelaysUpdated g groupLink relays =
[ "group link:",
plain $ maybe cReqStr strEncode shortLink
]
<> ["SimpleX name: " <> plain (shortNameInfoStr ni) | Just ni <- [groupDomainName g]]
<> ["SimpleX name: " <> plain (shortNameInfoStr ni) | Just ni <- [groupSimplexName g]]
where
GroupLink {connLinkContact = CCLink cReq shortLink} = groupLink
cReqStr = strEncode $ simplexChatContact cReq
@@ -1809,12 +1809,12 @@ viewContactBadge = maybe [] $ \lb ->
in [plain (textEncode badgeType <> " badge - " <> st), plain expiry]
viewContactInfo :: Contact -> Maybe ConnectionStats -> Maybe Profile -> [StyledString]
viewContactInfo ct@Contact {contactId, profile = LocalProfile {localAlias, contactLink, localBadge, simplexName, contactDomainVerification}, activeConn, uiThemes, customData} stats incognitoProfile =
viewContactInfo ct@Contact {contactId, profile = LocalProfile {localAlias, contactLink, localBadge, simplexName, contactNameVerification}, activeConn, uiThemes, customData} stats incognitoProfile =
["contact ID: " <> sShow contactId]
<> viewContactBadge localBadge
<> maybe [] viewConnectionStats stats
<> maybe [] (\l -> ["contact address: " <> plain (strEncode (simplexChatContact' l))]) contactLink
<> simplexNameStatus (claimName <$> simplexName) contactDomainVerification (isJust (claimProof =<< simplexName))
<> simplexNameStatus (claimName <$> simplexName) contactNameVerification (isJust (claimProof =<< simplexName))
<> maybe
["you've shared main profile with this contact"]
(\p -> ["you've shared incognito profile with this contact: " <> incognitoProfile' p])
@@ -2225,11 +2225,11 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
Just _ -> maybe True (\c -> connStatus c == ConnPrepared) activeConn
_ -> False
contactNameLine :: Contact -> [StyledString]
contactNameLine Contact {profile = LocalProfile {simplexName, contactDomainVerification}} =
simplexNameStatus (claimName <$> simplexName) contactDomainVerification (isJust (claimProof =<< simplexName))
contactNameLine Contact {profile = LocalProfile {simplexName, contactNameVerification}} =
simplexNameStatus (claimName <$> simplexName) contactNameVerification (isJust (claimProof =<< simplexName))
groupNameLine :: GroupInfo -> [StyledString]
groupNameLine g'@GroupInfo {groupDomainVerification, groupProfile = GroupProfile {publicGroup}} =
simplexNameStatus (groupDomainName g') groupDomainVerification (isJust (claimProof =<< (publicGroup >>= publicGroupAccess >>= publicGroupClaim)))
groupNameLine g'@GroupInfo {groupNameVerification, groupProfile = GroupProfile {publicGroup}} =
simplexNameStatus (groupSimplexName g') groupNameVerification (isJust (claimProof =<< (publicGroup >>= publicGroupAccess >>= publicGroupClaim)))
viewSigVerification = \case
Just OVVerified -> ["owner signature: verified"]
Just (OVFailed r) -> ["owner signature: FAILED (" <> plain r <> ")"]