diff --git a/src/Simplex/Chat/Badges.hs b/src/Simplex/Chat/Badges.hs index 957c9f8eb8..f0ebdf6dcf 100644 --- a/src/Simplex/Chat/Badges.hs +++ b/src/Simplex/Chat/Badges.hs @@ -60,7 +60,7 @@ data BadgeType = BTSupporter | BTBusiness | BTLegend - | BTCFInvestor + | BTInvestor | BTUnknown Text deriving (Eq, Show) @@ -69,13 +69,13 @@ instance TextEncoding BadgeType where BTSupporter -> "supporter" BTBusiness -> "business" BTLegend -> "legend" - BTCFInvestor -> "cf_investor" + BTInvestor -> "investor" BTUnknown tag -> tag textDecode s = Just $ case s of "supporter" -> BTSupporter "business" -> BTBusiness "legend" -> BTLegend - "cf_investor" -> BTCFInvestor + "investor" -> BTInvestor tag -> BTUnknown tag instance ToJSON BadgeType where @@ -142,7 +142,8 @@ data BadgeCredential = BadgeCredential { masterKey :: BadgeMasterKey, signature :: BBSSignature, badgeExpiry :: Maybe UTCTime, - badgeType :: BadgeType + badgeType :: BadgeType, + badgeExtra :: Text } deriving (Eq, Show) @@ -150,7 +151,8 @@ data SupporterBadge = SupporterBadge { proof :: BBSProof, presHeader :: BBSPresHeader, badgeExpiry :: Maybe UTCTime, - badgeType :: BadgeType + badgeType :: BadgeType, + badgeExtra :: Text } deriving (Eq, Show) @@ -160,21 +162,21 @@ bbsBadgeHeader :: BBSHeader bbsBadgeHeader = BBSHeader "SimpleX badges v1" bbsBadgeMessageCount :: Int -bbsBadgeMessageCount = 3 +bbsBadgeMessageCount = 4 bbsBadgeDisclosedIndexes :: [Int] -bbsBadgeDisclosedIndexes = [1, 2] +bbsBadgeDisclosedIndexes = [1, 2, 3] -- Message encoding encodeExpiry :: Maybe UTCTime -> ByteString encodeExpiry = maybe "lifetime" strEncode -badgeMessages :: BadgeMasterKey -> Maybe UTCTime -> BadgeType -> [ByteString] -badgeMessages (BadgeMasterKey ms) expiry bt = [ms, encodeExpiry expiry, encodeUtf8 (textEncode bt)] +badgeMessages :: BadgeMasterKey -> Maybe UTCTime -> BadgeType -> Text -> [ByteString] +badgeMessages (BadgeMasterKey ms) expiry bt extra = [ms, encodeExpiry expiry, encodeUtf8 (textEncode bt), encodeUtf8 extra] -badgeDisclosedMessages :: Maybe UTCTime -> BadgeType -> [ByteString] -badgeDisclosedMessages expiry bt = [encodeExpiry expiry, encodeUtf8 (textEncode bt)] +badgeDisclosedMessages :: Maybe UTCTime -> BadgeType -> Text -> [ByteString] +badgeDisclosedMessages expiry bt extra = [encodeExpiry expiry, encodeUtf8 (textEncode bt), encodeUtf8 extra] -- Payment verification (stub - always passes) @@ -185,29 +187,30 @@ verifyPayment _payment req = pure $ Just (VerifiedBadgeRequest req) issueBadge :: BBSSecretKey -> BBSPublicKey -> VerifiedBadgeRequest -> IO (Either String BadgeCredential) issueBadge sk pk (VerifiedBadgeRequest BadgeRequest {masterKey, badgeType, expiry}) = - fmap mkCred <$> bbsSign sk pk bbsBadgeHeader (badgeMessages masterKey expiry badgeType) + fmap mkCred <$> bbsSign sk pk bbsBadgeHeader (badgeMessages masterKey expiry badgeType badgeExtra) where - mkCred sig = BadgeCredential {masterKey, signature = sig, badgeExpiry = expiry, badgeType} + badgeExtra = "" -- reserved, empty for now + mkCred sig = BadgeCredential {masterKey, signature = sig, badgeExpiry = expiry, badgeType, badgeExtra} -- Client-side: verify the credential received from server verifyBadgeSignature :: BBSPublicKey -> BadgeCredential -> IO Bool -verifyBadgeSignature pk BadgeCredential {masterKey, signature, badgeExpiry, badgeType} = - bbsVerify pk signature bbsBadgeHeader (badgeMessages masterKey badgeExpiry badgeType) +verifyBadgeSignature pk BadgeCredential {masterKey, signature, badgeExpiry, badgeType, badgeExtra} = + bbsVerify pk signature bbsBadgeHeader (badgeMessages masterKey badgeExpiry badgeType badgeExtra) -- Client-side: generate a proof for a contact/group generateBadgeProof :: BBSPublicKey -> BadgeCredential -> BBSPresHeader -> IO (Either String SupporterBadge) -generateBadgeProof pk BadgeCredential {masterKey, signature, badgeExpiry, badgeType} ph = - fmap mkBadge <$> bbsProofGen pk signature bbsBadgeHeader ph bbsBadgeDisclosedIndexes (badgeMessages masterKey badgeExpiry badgeType) +generateBadgeProof pk BadgeCredential {masterKey, signature, badgeExpiry, badgeType, badgeExtra} ph = + fmap mkBadge <$> bbsProofGen pk signature bbsBadgeHeader ph bbsBadgeDisclosedIndexes (badgeMessages masterKey badgeExpiry badgeType badgeExtra) where - mkBadge p = SupporterBadge {proof = p, presHeader = ph, badgeExpiry, badgeType} + mkBadge p = SupporterBadge {proof = p, presHeader = ph, badgeExpiry, badgeType, badgeExtra} -- Recipient-side: verify a badge proof verifyBadge :: BBSPublicKey -> SupporterBadge -> IO Bool -verifyBadge pk SupporterBadge {proof, presHeader, badgeExpiry, badgeType} = - bbsProofVerify pk proof bbsBadgeHeader presHeader bbsBadgeDisclosedIndexes bbsBadgeMessageCount (badgeDisclosedMessages badgeExpiry badgeType) +verifyBadge pk SupporterBadge {proof, presHeader, badgeExpiry, badgeType, badgeExtra} = + bbsProofVerify pk proof bbsBadgeHeader presHeader bbsBadgeDisclosedIndexes bbsBadgeMessageCount (badgeDisclosedMessages badgeExpiry badgeType badgeExtra) verifyBadge_ :: BBSPublicKey -> Maybe SupporterBadge -> IO Bool verifyBadge_ = maybe (pure False) . verifyBadge @@ -226,17 +229,17 @@ instance FromField BadgeType where fromField = fromTextField_ textDecode instance ToField BadgeType where toField = toField . textEncode -type BadgeRow = (Maybe ByteString, Maybe ByteString, Maybe UTCTime, Maybe Text, Maybe BoolInt) +type BadgeRow = (Maybe ByteString, Maybe ByteString, Maybe UTCTime, Maybe Text, Maybe BoolInt, Maybe Text) badgeToRow :: Maybe SupporterBadge -> Bool -> BadgeRow -badgeToRow (Just SupporterBadge {proof = BBSProof p, presHeader = BBSPresHeader ph, badgeExpiry, badgeType}) verified = - (Just p, Just ph, badgeExpiry, Just (textEncode badgeType), Just (BI verified)) -badgeToRow _ _ = (Nothing, Nothing, Nothing, Nothing, Just (BI False)) +badgeToRow (Just SupporterBadge {proof = BBSProof p, presHeader = BBSPresHeader ph, badgeExpiry, badgeType, badgeExtra}) verified = + (Just p, Just ph, badgeExpiry, Just (textEncode badgeType), Just (BI verified), Just badgeExtra) +badgeToRow _ _ = (Nothing, Nothing, Nothing, Nothing, Just (BI False), Nothing) rowToBadge :: UTCTime -> BadgeRow -> Maybe LocalBadge -rowToBadge now (Just p, Just ph, badgeExpiry, Just btText, verified_) = do +rowToBadge now (Just p, Just ph, badgeExpiry, Just btText, verified_, extra_) = do bt <- textDecode btText - let b = SupporterBadge {proof = BBSProof p, presHeader = BBSPresHeader ph, badgeExpiry, badgeType = bt} + let b = SupporterBadge {proof = BBSProof p, presHeader = BBSPresHeader ph, badgeExpiry, badgeType = bt, badgeExtra = maybe "" id extra_} verified = maybe False unBI verified_ Just LocalBadge {badgeStatus = mkBadgeStatus now verified b, badge = b} rowToBadge _ _ = Nothing diff --git a/src/Simplex/Chat/Store/Connections.hs b/src/Simplex/Chat/Store/Connections.hs index 3fde701230..1b1f00866e 100644 --- a/src/Simplex/Chat/Store/Connections.hs +++ b/src/Simplex/Chat/Store/Connections.hs @@ -116,7 +116,7 @@ getConnectionEntity db cxt user@User {userId, userContactId} agentConnId = do p.preferences, c.user_preferences, c.created_at, c.updated_at, c.chat_ts, c.conn_full_link_to_connect, c.conn_short_link_to_connect, c.welcome_shared_msg_id, c.request_shared_msg_id, c.contact_request_id, c.contact_group_member_id, c.contact_grp_inv_sent, c.grp_direct_inv_link, c.grp_direct_inv_from_group_id, c.grp_direct_inv_from_group_member_id, c.grp_direct_inv_from_member_conn_id, c.grp_direct_inv_started_connection, c.ui_themes, c.chat_deleted, c.custom_data, c.chat_item_ttl, - p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified + p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra FROM contacts c JOIN contact_profiles p ON c.contact_profile_id = p.contact_profile_id WHERE c.user_id = ? AND c.contact_id = ? AND c.contact_status = ? AND c.deleted = 0 @@ -156,13 +156,13 @@ getConnectionEntity db cxt user@User {userId, userContactId} agentConnId = do mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, -- GroupInfo {membership = GroupMember {memberProfile}} pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.chat_peer_type, pu.local_alias, pu.preferences, - pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, + pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, pu.badge_extra, mu.created_at, mu.updated_at, mu.support_chat_ts, mu.support_chat_items_unread, mu.support_chat_items_member_attention, mu.support_chat_items_mentions, mu.support_chat_last_msg_from_member_ts, mu.member_pub_key, mu.relay_link, -- from GroupMember m.group_member_id, m.group_id, m.index_in_group, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences, - p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, + p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, m.created_at, m.updated_at, m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts, m.member_pub_key, m.relay_link FROM group_members m diff --git a/src/Simplex/Chat/Store/ContactRequest.hs b/src/Simplex/Chat/Store/ContactRequest.hs index 3890bcae2c..3d084acb4d 100644 --- a/src/Simplex/Chat/Store/ContactRequest.hs +++ b/src/Simplex/Chat/Store/ContactRequest.hs @@ -116,7 +116,7 @@ createOrUpdateContactRequest cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.request_shared_msg_id, ct.contact_request_id, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.grp_direct_inv_link, ct.grp_direct_inv_from_group_id, ct.grp_direct_inv_from_group_member_id, ct.grp_direct_inv_from_member_conn_id, ct.grp_direct_inv_started_connection, ct.ui_themes, ct.chat_deleted, ct.custom_data, ct.chat_item_ttl, - cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, + cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra, -- Connection c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, @@ -152,7 +152,7 @@ createOrUpdateContactRequest cr.pq_support, cr.welcome_shared_msg_id, cr.request_shared_msg_id, p.preferences, cr.created_at, cr.updated_at, cr.peer_chat_min_version, cr.peer_chat_max_version, - p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified + p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra FROM contact_requests cr JOIN contact_profiles p USING (contact_profile_id) WHERE cr.user_id = ? @@ -168,7 +168,7 @@ createOrUpdateContactRequest liftIO $ DB.execute db - "INSERT INTO contact_profiles (display_name, full_name, short_descr, image, contact_link, user_id, local_alias, preferences, created_at, updated_at, badge_proof, badge_pres_header, badge_expiry, badge_type, badge_verified) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + "INSERT INTO contact_profiles (display_name, full_name, short_descr, image, contact_link, user_id, local_alias, preferences, created_at, updated_at, badge_proof, badge_pres_header, badge_expiry, badge_type, badge_verified, badge_extra) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" ((displayName, fullName, shortDescr, image, contactLink, userId) :. ("" :: LocalAlias, preferences, currentTs, currentTs) :. badgeToRow badge badgeVerified) profileId <- liftIO $ insertedRowId db liftIO $ @@ -245,7 +245,8 @@ createOrUpdateContactRequest badge_pres_header = ?, badge_expiry = ?, badge_type = ?, - badge_verified = ? + badge_verified = ?, + badge_extra = ? WHERE contact_profile_id IN ( SELECT contact_profile_id FROM contact_requests diff --git a/src/Simplex/Chat/Store/Direct.hs b/src/Simplex/Chat/Store/Direct.hs index 0d3ba8c2b7..7bca2e34ce 100644 --- a/src/Simplex/Chat/Store/Direct.hs +++ b/src/Simplex/Chat/Store/Direct.hs @@ -320,7 +320,7 @@ getContactByConnReqHash db cxt user@User {userId} cReqHash1 cReqHash2 = do cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.request_shared_msg_id, ct.contact_request_id, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.grp_direct_inv_link, ct.grp_direct_inv_from_group_id, ct.grp_direct_inv_from_group_member_id, ct.grp_direct_inv_from_member_conn_id, ct.grp_direct_inv_started_connection, ct.ui_themes, ct.chat_deleted, ct.custom_data, ct.chat_item_ttl, - cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, + cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra, -- Connection c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, @@ -712,7 +712,7 @@ updateContactProfile_' db userId profileId Profile {displayName, fullName, short [sql| UPDATE contact_profiles SET display_name = ?, full_name = ?, short_descr = ?, image = ?, contact_link = ?, preferences = ?, chat_peer_type = ?, updated_at = ?, - badge_proof = ?, badge_pres_header = ?, badge_expiry = ?, badge_type = ?, badge_verified = ? + badge_proof = ?, badge_pres_header = ?, badge_expiry = ?, badge_type = ?, badge_verified = ?, badge_extra = ? WHERE user_id = ? AND contact_profile_id = ? |] ((displayName, fullName, shortDescr, image, contactLink, preferences, peerType, updatedAt) :. badgeToRow badge badgeVerified :. (userId, profileId)) @@ -730,7 +730,7 @@ updateMemberContactProfileReset_' db userId profileId Profile {displayName, full [sql| UPDATE contact_profiles SET display_name = ?, full_name = ?, short_descr = ?, image = ?, contact_link = NULL, preferences = NULL, updated_at = ?, - badge_proof = ?, badge_pres_header = ?, badge_expiry = ?, badge_type = ?, badge_verified = ? + badge_proof = ?, badge_pres_header = ?, badge_expiry = ?, badge_type = ?, badge_verified = ?, badge_extra = ? WHERE user_id = ? AND contact_profile_id = ? |] ((displayName, fullName, shortDescr, image, updatedAt) :. badgeToRow badge badgeVerified :. (userId, profileId)) @@ -748,7 +748,7 @@ updateMemberContactProfile_' db userId profileId Profile {displayName, fullName, [sql| UPDATE contact_profiles SET display_name = ?, full_name = ?, short_descr = ?, image = ?, updated_at = ?, - badge_proof = ?, badge_pres_header = ?, badge_expiry = ?, badge_type = ?, badge_verified = ? + badge_proof = ?, badge_pres_header = ?, badge_expiry = ?, badge_type = ?, badge_verified = ?, badge_extra = ? WHERE user_id = ? AND contact_profile_id = ? |] ((displayName, fullName, shortDescr, image, updatedAt) :. badgeToRow badge badgeVerified :. (userId, profileId)) @@ -809,7 +809,7 @@ contactRequestQuery = cr.pq_support, cr.welcome_shared_msg_id, cr.request_shared_msg_id, p.preferences, cr.created_at, cr.updated_at, cr.peer_chat_min_version, cr.peer_chat_max_version, - p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified + p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra FROM contact_requests cr JOIN contact_profiles p USING (contact_profile_id) |] @@ -929,7 +929,7 @@ getContact_ db cxt user@User {userId} contactId deleted = do cp.preferences, ct.user_preferences, ct.created_at, ct.updated_at, ct.chat_ts, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect, ct.welcome_shared_msg_id, ct.request_shared_msg_id, ct.contact_request_id, ct.contact_group_member_id, ct.contact_grp_inv_sent, ct.grp_direct_inv_link, ct.grp_direct_inv_from_group_id, ct.grp_direct_inv_from_group_member_id, ct.grp_direct_inv_from_member_conn_id, ct.grp_direct_inv_started_connection, ct.ui_themes, ct.chat_deleted, ct.custom_data, ct.chat_item_ttl, - cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, + cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra, -- Connection c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id, c.conn_status, c.conn_type, c.contact_conn_initiated, c.local_alias, c.contact_id, c.group_member_id, c.user_contact_link_id, c.created_at, c.security_code, c.security_code_verified_at, c.pq_support, c.pq_encryption, c.pq_snd_enabled, c.pq_rcv_enabled, c.auth_err_counter, c.quota_err_counter, diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index 9be40cd150..3bce76b87a 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -1734,7 +1734,7 @@ createJoiningMember liftIO $ DB.execute db - "INSERT INTO contact_profiles (display_name, full_name, short_descr, image, contact_link, user_id, preferences, created_at, updated_at, badge_proof, badge_pres_header, badge_expiry, badge_type, badge_verified) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + "INSERT INTO contact_profiles (display_name, full_name, short_descr, image, contact_link, user_id, preferences, created_at, updated_at, badge_proof, badge_pres_header, badge_expiry, badge_type, badge_verified, badge_extra) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" ((displayName, fullName, shortDescr, image, contactLink, userId, preferences, currentTs, currentTs) :. badgeToRow badge badgeVerified) profileId <- liftIO $ insertedRowId db case cReqMemberId_ of @@ -2095,7 +2095,7 @@ createNewMemberProfile_ db User {userId} Profile {displayName, fullName, shortDe badgeVerified <- verifyBadge_ srvBadgePublicKey badge DB.execute db - "INSERT INTO contact_profiles (display_name, full_name, short_descr, image, contact_link, user_id, preferences, created_at, updated_at, badge_proof, badge_pres_header, badge_expiry, badge_type, badge_verified) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + "INSERT INTO contact_profiles (display_name, full_name, short_descr, image, contact_link, user_id, preferences, created_at, updated_at, badge_proof, badge_pres_header, badge_expiry, badge_type, badge_verified, badge_extra) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" ((displayName, fullName, shortDescr, image, contactLink, userId, preferences, createdAt, createdAt) :. badgeToRow badge badgeVerified) profileId <- insertedRowId db pure $ Right (ldn, profileId, badgeVerified) diff --git a/src/Simplex/Chat/Store/Messages.hs b/src/Simplex/Chat/Store/Messages.hs index a137ac94b3..8927ef2ec0 100644 --- a/src/Simplex/Chat/Store/Messages.hs +++ b/src/Simplex/Chat/Store/Messages.hs @@ -707,7 +707,7 @@ getChatItemQuote_ db User {userId, userContactId} chatDirection QuotedMsg {msgRe m.group_member_id, m.group_id, m.index_in_group, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences, - p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, + p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, m.created_at, m.updated_at, m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts, m.member_pub_key, m.relay_link FROM group_members m @@ -1131,7 +1131,7 @@ getContactRequestChatPreviews_ db User {userId} pagination clq = do cr.pq_support, cr.welcome_shared_msg_id, cr.request_shared_msg_id, p.preferences, cr.created_at, cr.updated_at, cr.peer_chat_min_version, cr.peer_chat_max_version, - p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified + p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra FROM contact_requests cr JOIN contact_profiles p ON p.contact_profile_id = cr.contact_profile_id JOIN user_contact_links uc ON uc.user_contact_link_id = cr.user_contact_link_id @@ -3041,7 +3041,7 @@ getGroupChatItem db User {userId, userContactId} groupId itemId = ExceptT $ do m.group_member_id, m.group_id, m.index_in_group, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences, - p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, + p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, m.created_at, m.updated_at, m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts, m.member_pub_key, m.relay_link, -- quoted ChatItem @@ -3050,14 +3050,14 @@ getGroupChatItem db User {userId, userContactId} groupId itemId = ExceptT $ do rm.group_member_id, rm.group_id, rm.index_in_group, rm.member_id, rm.peer_chat_min_version, rm.peer_chat_max_version, rm.member_role, rm.member_category, rm.member_status, rm.show_messages, rm.member_restriction, rm.invited_by, rm.invited_by_group_member_id, rm.local_display_name, rm.contact_id, rm.contact_profile_id, rp.contact_profile_id, rp.display_name, rp.full_name, rp.short_descr, rp.image, rp.contact_link, rp.chat_peer_type, rp.local_alias, rp.preferences, - rp.badge_proof, rp.badge_pres_header, rp.badge_expiry, rp.badge_type, rp.badge_verified, + rp.badge_proof, rp.badge_pres_header, rp.badge_expiry, rp.badge_type, rp.badge_verified, rp.badge_extra, rm.created_at, rm.updated_at, rm.support_chat_ts, rm.support_chat_items_unread, rm.support_chat_items_member_attention, rm.support_chat_items_mentions, rm.support_chat_last_msg_from_member_ts, rm.member_pub_key, rm.relay_link, -- deleted by GroupMember dbm.group_member_id, dbm.group_id, dbm.index_in_group, dbm.member_id, dbm.peer_chat_min_version, dbm.peer_chat_max_version, dbm.member_role, dbm.member_category, dbm.member_status, dbm.show_messages, dbm.member_restriction, dbm.invited_by, dbm.invited_by_group_member_id, dbm.local_display_name, dbm.contact_id, dbm.contact_profile_id, dbp.contact_profile_id, dbp.display_name, dbp.full_name, dbp.short_descr, dbp.image, dbp.contact_link, dbp.chat_peer_type, dbp.local_alias, dbp.preferences, - dbp.badge_proof, dbp.badge_pres_header, dbp.badge_expiry, dbp.badge_type, dbp.badge_verified, + dbp.badge_proof, dbp.badge_pres_header, dbp.badge_expiry, dbp.badge_type, dbp.badge_verified, dbp.badge_extra, dbm.created_at, dbm.updated_at, dbm.support_chat_ts, dbm.support_chat_items_unread, dbm.support_chat_items_member_attention, dbm.support_chat_items_mentions, dbm.support_chat_last_msg_from_member_ts, dbm.member_pub_key, dbm.relay_link FROM chat_items i diff --git a/src/Simplex/Chat/Store/Postgres/Migrations/M20260516_supporter_badges.hs b/src/Simplex/Chat/Store/Postgres/Migrations/M20260516_supporter_badges.hs index 01fe42e1db..bacf3eb482 100644 --- a/src/Simplex/Chat/Store/Postgres/Migrations/M20260516_supporter_badges.hs +++ b/src/Simplex/Chat/Store/Postgres/Migrations/M20260516_supporter_badges.hs @@ -14,11 +14,13 @@ ALTER TABLE contact_profiles ADD COLUMN badge_pres_header BYTEA; ALTER TABLE contact_profiles ADD COLUMN badge_expiry TEXT; ALTER TABLE contact_profiles ADD COLUMN badge_type TEXT; ALTER TABLE contact_profiles ADD COLUMN badge_verified SMALLINT NOT NULL DEFAULT 0; +ALTER TABLE contact_profiles ADD COLUMN badge_extra TEXT; |] down_m20260516_supporter_badges :: Text down_m20260516_supporter_badges = [r| +ALTER TABLE contact_profiles DROP COLUMN badge_extra; ALTER TABLE contact_profiles DROP COLUMN badge_verified; ALTER TABLE contact_profiles DROP COLUMN badge_type; ALTER TABLE contact_profiles DROP COLUMN badge_proof; diff --git a/src/Simplex/Chat/Store/Postgres/Migrations/chat_schema.sql b/src/Simplex/Chat/Store/Postgres/Migrations/chat_schema.sql index c5db399807..acb3c37b0a 100644 --- a/src/Simplex/Chat/Store/Postgres/Migrations/chat_schema.sql +++ b/src/Simplex/Chat/Store/Postgres/Migrations/chat_schema.sql @@ -536,7 +536,8 @@ CREATE TABLE test_chat_schema.contact_profiles ( badge_pres_header bytea, badge_expiry text, badge_type text, - badge_verified smallint DEFAULT 0 NOT NULL + badge_verified smallint DEFAULT 0 NOT NULL, + badge_extra text ); diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/M20260516_supporter_badges.hs b/src/Simplex/Chat/Store/SQLite/Migrations/M20260516_supporter_badges.hs index b783d9bc58..05d46c8a34 100644 --- a/src/Simplex/Chat/Store/SQLite/Migrations/M20260516_supporter_badges.hs +++ b/src/Simplex/Chat/Store/SQLite/Migrations/M20260516_supporter_badges.hs @@ -13,11 +13,13 @@ ALTER TABLE contact_profiles ADD COLUMN badge_pres_header BLOB; ALTER TABLE contact_profiles ADD COLUMN badge_expiry TEXT; ALTER TABLE contact_profiles ADD COLUMN badge_type TEXT; ALTER TABLE contact_profiles ADD COLUMN badge_verified INTEGER NOT NULL DEFAULT 0; +ALTER TABLE contact_profiles ADD COLUMN badge_extra TEXT; |] down_m20260516_supporter_badges :: Query down_m20260516_supporter_badges = [sql| +ALTER TABLE contact_profiles DROP COLUMN badge_extra; ALTER TABLE contact_profiles DROP COLUMN badge_verified; ALTER TABLE contact_profiles DROP COLUMN badge_type; ALTER TABLE contact_profiles DROP COLUMN badge_expiry; diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql b/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql index 871490db43..55d4080f04 100644 --- a/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql +++ b/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql @@ -24,7 +24,8 @@ CREATE TABLE contact_profiles( badge_pres_header BLOB, badge_expiry TEXT, badge_type TEXT, - badge_verified INTEGER NOT NULL DEFAULT 0 + badge_verified INTEGER NOT NULL DEFAULT 0, + badge_extra TEXT ) STRICT; CREATE TABLE users( user_id INTEGER PRIMARY KEY, diff --git a/src/Simplex/Chat/Store/Shared.hs b/src/Simplex/Chat/Store/Shared.hs index 29d6f7f370..579261e9ba 100644 --- a/src/Simplex/Chat/Store/Shared.hs +++ b/src/Simplex/Chat/Store/Shared.hs @@ -418,7 +418,7 @@ createContact_ db User {userId} Profile {displayName, fullName, shortDescr, imag badgeVerified <- verifyBadge_ srvBadgePublicKey badge DB.execute db - "INSERT INTO contact_profiles (display_name, full_name, short_descr, image, contact_link, chat_peer_type, user_id, local_alias, preferences, created_at, updated_at, badge_proof, badge_pres_header, badge_expiry, badge_type, badge_verified) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + "INSERT INTO contact_profiles (display_name, full_name, short_descr, image, contact_link, chat_peer_type, user_id, local_alias, preferences, created_at, updated_at, badge_proof, badge_pres_header, badge_expiry, badge_type, badge_verified, badge_extra) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" ((displayName, fullName, shortDescr, image, contactLink, peerType) :. (userId, localAlias, preferences, currentTs, currentTs) :. badgeToRow badge badgeVerified) profileId <- insertedRowId db DB.execute @@ -525,7 +525,7 @@ getProfileById db userId profileId = do db [sql| SELECT cp.contact_profile_id, cp.display_name, cp.full_name, cp.short_descr, cp.image, cp.contact_link, cp.chat_peer_type, cp.local_alias, cp.preferences, - cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified + cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra FROM contact_profiles cp WHERE cp.user_id = ? AND cp.contact_profile_id = ? |] @@ -749,7 +749,7 @@ groupMemberQuery = SELECT m.group_member_id, m.group_id, m.index_in_group, m.member_id, m.peer_chat_min_version, m.peer_chat_max_version, m.member_role, m.member_category, m.member_status, m.show_messages, m.member_restriction, m.invited_by, m.invited_by_group_member_id, m.local_display_name, m.contact_id, m.contact_profile_id, p.contact_profile_id, p.display_name, p.full_name, p.short_descr, p.image, p.contact_link, p.chat_peer_type, p.local_alias, p.preferences, - p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, + p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, m.created_at, m.updated_at, m.support_chat_ts, m.support_chat_items_unread, m.support_chat_items_member_attention, m.support_chat_items_mentions, m.support_chat_last_msg_from_member_ts, m.member_pub_key, m.relay_link, c.connection_id, c.agent_conn_id, c.conn_level, c.via_contact, c.via_user_contact_link, c.via_group_link, c.group_link_id, c.xcontact_id, c.custom_user_profile_id, @@ -794,7 +794,7 @@ groupInfoQueryFields = mu.group_member_id, mu.group_id, mu.index_in_group, mu.member_id, mu.peer_chat_min_version, mu.peer_chat_max_version, mu.member_role, mu.member_category, mu.member_status, mu.show_messages, mu.member_restriction, mu.invited_by, mu.invited_by_group_member_id, mu.local_display_name, mu.contact_id, mu.contact_profile_id, pu.contact_profile_id, pu.display_name, pu.full_name, pu.short_descr, pu.image, pu.contact_link, pu.chat_peer_type, pu.local_alias, pu.preferences, - pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, + pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, pu.badge_extra, mu.created_at, mu.updated_at, mu.support_chat_ts, mu.support_chat_items_unread, mu.support_chat_items_member_attention, mu.support_chat_items_mentions, mu.support_chat_last_msg_from_member_ts, mu.member_pub_key, mu.relay_link |] diff --git a/tests/BadgeTests.hs b/tests/BadgeTests.hs index 899961148d..085125afe4 100644 --- a/tests/BadgeTests.hs +++ b/tests/BadgeTests.hs @@ -41,12 +41,12 @@ testFullWorkflow = do testTamperedType :: IO () testTamperedType = do (pk, SupporterBadge {proof, presHeader, badgeExpiry}) <- issueBadgeProof BTSupporter (Just futureTime) - verifyBadge pk (SupporterBadge {proof, presHeader, badgeExpiry, badgeType = BTBusiness}) >>= (`shouldBe` False) + verifyBadge pk (SupporterBadge {proof, presHeader, badgeExpiry, badgeType = BTBusiness, badgeExtra = ""}) >>= (`shouldBe` False) testTamperedExpiry :: IO () testTamperedExpiry = do (pk, SupporterBadge {proof, presHeader, badgeType}) <- issueBadgeProof BTSupporter (Just futureTime) - verifyBadge pk (SupporterBadge {proof, presHeader, badgeExpiry = Just pastTime, badgeType}) >>= (`shouldBe` False) + verifyBadge pk (SupporterBadge {proof, presHeader, badgeExpiry = Just pastTime, badgeType, badgeExtra = ""}) >>= (`shouldBe` False) testWrongKey :: IO () testWrongKey = do @@ -66,7 +66,7 @@ testExpiryCheck = do testLifetimeBadge :: IO () testLifetimeBadge = do now <- getCurrentTime - (pk, badge) <- issueBadgeProof BTCFInvestor Nothing + (pk, badge) <- issueBadgeProof BTInvestor Nothing verifyBadge pk badge >>= (`shouldBe` True) mkBadgeStatus now True badge `shouldBe` BSActive