This commit is contained in:
Evgeny @ SimpleX Chat
2026-07-14 20:46:37 +00:00
parent 7787e6119c
commit 78de359db1
7 changed files with 41 additions and 40 deletions
+24 -18
View File
@@ -1265,35 +1265,41 @@ memberInfo g m@GroupMember {memberId, memberRole, memberProfile, memberPubKey, a
redactedMemberProfile :: GroupInfo -> GroupMember -> Profile -> Profile
redactedMemberProfile g m Profile {displayName, fullName, shortDescr, description, image, contactLink = lnk, peerType, badge, contactDomain} =
Profile {displayName, fullName, shortDescr = removeSimplexLink =<< shortDescr, description = redactGroupDescription g m =<< description, image, contactLink, preferences = Nothing, peerType, badge, contactDomain = redactedDomain}
Profile {displayName, fullName, shortDescr = redactLinkedText dropWholeOnLink allowSimplexLinks =<< shortDescr, description = redactGroupDescription g m =<< description, image, contactLink, preferences = Nothing, peerType, badge, contactDomain = redactedDomain}
where
contactLink = if allowSimplexLinks then lnk else Nothing
redactedDomain = if allowDirect then (\d -> d {proof = Nothing} :: SimplexDomainClaim) <$> contactDomain else Nothing
allowDirect = groupFeatureMemberAllowed SGFDirectMessages m g
allowSimplexLinks = groupFeatureMemberAllowed SGFSimplexLinks m g && allowDirect
removeSimplexLink s
| allowSimplexLinks = Just s
| hasObfuscatedSimplexLink s = Nothing
| otherwise = maybe (Just s) (\fts -> if any ftIsSimplexLink fts then Nothing else Just s) $ parseMaybeMarkdownList s
allowSimplexLinks = memberLinksAllowed g m
-- redact only the description of an incoming member profile (receive side), per the group's link/name policy
redactMemberProfileDescription :: GroupInfo -> GroupMember -> Profile -> Profile
redactMemberProfileDescription g m p@Profile {description} = p {description = redactGroupDescription g m =<< description}
redactMemberProfileDescription g m p@Profile {description} =
p {description = redactGroupDescription g m =<< description}
-- strip link/name spans inline from a group member's description (keeping the prose), dropping the whole field only on an obfuscated link
redactGroupDescription :: GroupInfo -> GroupMember -> Text -> Maybe Text
redactGroupDescription g m s
redactGroupDescription g m = redactLinkedText stripLinkSpans (memberLinksAllowed g m)
memberLinksAllowed :: GroupInfo -> GroupMember -> Bool
memberLinksAllowed g m = groupFeatureMemberAllowed SGFSimplexLinks m g && groupFeatureMemberAllowed SGFDirectMessages m g
redactLinkedText :: (Text -> [FormattedText] -> Maybe Text) -> Bool -> Text -> Maybe Text
redactLinkedText fromSpans allowSimplexLinks s
| allowSimplexLinks = Just s
| hasObfuscatedSimplexLink s = Nothing
| otherwise = case parseMaybeMarkdownList s of
Nothing -> Just s
Just fts ->
let kept = T.concat [t | FormattedText f t <- fts, not (maybe False isLinkOrName f)]
in if T.null (T.strip kept) then Nothing else Just kept
| otherwise = maybe (Just s) (fromSpans s) $ parseMaybeMarkdownList s
dropWholeOnLink :: Text -> [FormattedText] -> Maybe Text
dropWholeOnLink s fts
| any ftIsSimplexLink fts = Nothing
| otherwise = Just s
stripLinkSpans :: Text -> [FormattedText] -> Maybe Text
stripLinkSpans _ fts
| T.null (T.strip kept) = Nothing
| otherwise = Just kept
where
allowDirect = groupFeatureMemberAllowed SGFDirectMessages m g
allowSimplexLinks = groupFeatureMemberAllowed SGFSimplexLinks m g && allowDirect
isLinkOrName f = isLink f || case f of Mention {} -> True; _ -> False
kept = T.concat [t | FormattedText f t <- fts, not (maybe False linkOrMention f)]
linkOrMention f = isLink f || case f of Mention {} -> True; _ -> False
-- Roles carried by the roster; owners are on the link, not the roster.
isRosterRole :: GroupMemberRole -> Bool
+3 -3
View File
@@ -353,9 +353,9 @@ updateUserProfile db user p'
DB.execute db "UPDATE users SET user_member_profile_updated_at = ? WHERE user_id = ?" (currentTs, userId)
pure $ Just currentTs
| otherwise = pure userMemberProfileUpdatedAt
userMemberProfileChanged = newName /= displayName || fn' /= fullName || d' /= shortDescr || img' /= image
User {userId, userContactId, localDisplayName, profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, localBadge, localAlias}, userMemberProfileUpdatedAt} = user
Profile {displayName = newName, fullName = fn', shortDescr = d', image = img', preferences} = p'
userMemberProfileChanged = newName /= displayName || fn' /= fullName || d' /= shortDescr || desc' /= description || img' /= image
User {userId, userContactId, localDisplayName, profile = LocalProfile {profileId, displayName, fullName, shortDescr, description, image, localBadge, localAlias}, userMemberProfileUpdatedAt} = user
Profile {displayName = newName, fullName = fn', shortDescr = d', description = desc', image = img', preferences} = p'
fullPreferences = fullPreferences' preferences
-- own profile field update; leaves the badge columns alone (the credential is owned by setUserBadge/addUserBadge)
+13 -8
View File
@@ -1959,14 +1959,15 @@ viewSwitchPhase = \case
SPCompleted -> "changed address"
viewUserProfileUpdated :: Profile -> Profile -> UserProfileUpdateSummary -> [StyledString]
viewUserProfileUpdated Profile {displayName = n, fullName, shortDescr, image, contactLink, preferences} Profile {displayName = n', fullName = fullName', shortDescr = shortDescr', image = image', contactLink = contactLink', preferences = prefs'} summary =
viewUserProfileUpdated Profile {displayName = n, fullName, shortDescr, description, image, contactLink, preferences} Profile {displayName = n', fullName = fullName', shortDescr = shortDescr', description = description', image = image', contactLink = contactLink', preferences = prefs'} summary =
profileUpdated <> viewPrefsUpdated preferences prefs'
where
UserProfileUpdateSummary {updateSuccesses = s, updateFailures = f} = summary
profileUpdated
| n == n' && fullName == fullName' && shortDescr == shortDescr' && image == image' && contactLink == contactLink' = []
| n == n' && fullName == fullName' && shortDescr == shortDescr' && image == image' = [if isNothing contactLink' then "contact address removed" else "new contact address set"]
| n == n' && fullName == fullName' && shortDescr == shortDescr' = [if isNothing image' then "profile image removed" else "profile image updated"]
| n == n' && fullName == fullName' && shortDescr == shortDescr' && description == description' && image == image' && contactLink == contactLink' = []
| n == n' && fullName == fullName' && shortDescr == shortDescr' && description == description' && image == image' = [if isNothing contactLink' then "contact address removed" else "new contact address set"]
| n == n' && fullName == fullName' && shortDescr == shortDescr' && description == description' = [if isNothing image' then "profile image removed" else "profile image updated"]
| n == n' && fullName == fullName' && shortDescr == shortDescr' = ["user description " <> (if maybe True T.null description' then "removed" else "changed to " <> maybe "" plain description') <> notified]
| n == n' && fullName == fullName' = ["user bio " <> (if maybe True T.null shortDescr' then "removed" else "changed to " <> maybe "" plain shortDescr') <> notified]
| n == n' = ["user full name " <> (if T.null fullName' || fullName' == n' then "removed" else "changed to " <> plain fullName') <> notified]
| otherwise = ["user profile is changed to " <> ttyFullName n' fullName' shortDescr' <> notified]
@@ -2257,13 +2258,17 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
viewContactUpdated :: Contact -> Contact -> [StyledString]
viewContactUpdated
Contact {localDisplayName = n, profile = LocalProfile {fullName, shortDescr, contactLink}}
Contact {localDisplayName = n', profile = LocalProfile {fullName = fullName', shortDescr = shortDescr', contactLink = contactLink'}}
| n == n' && fullName == fullName' && shortDescr == shortDescr' && contactLink == contactLink' = []
| n == n' && fullName == fullName' && shortDescr == shortDescr' =
Contact {localDisplayName = n, profile = LocalProfile {fullName, shortDescr, description, contactLink}}
Contact {localDisplayName = n', profile = LocalProfile {fullName = fullName', shortDescr = shortDescr', description = description', contactLink = contactLink'}}
| n == n' && fullName == fullName' && shortDescr == shortDescr' && description == description' && contactLink == contactLink' = []
| n == n' && fullName == fullName' && shortDescr == shortDescr' && description == description' =
if isNothing contactLink'
then [ttyContact n <> " removed contact address"]
else [ttyContact n <> " set new contact address, use " <> highlight ("/info " <> n) <> " to view"]
| n == n' && fullName == fullName' && shortDescr == shortDescr' =
if maybe True T.null description'
then ["contact " <> ttyContact n <> " removed description"]
else ["contact " <> ttyContact n <> " updated description: " <> maybe "" plain description']
| n == n' && fullName == fullName' =
if maybe True T.null shortDescr'
then ["contact " <> ttyContact n <> " removed bio"]