mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-07-02 22:11:54 +00:00
use domain without prefix in profiles and in database, rename fields and types
This commit is contained in:
@@ -156,9 +156,9 @@ enum ChatCommand: ChatCmdProtocol {
|
||||
case apiAddMyAddressShortLink(userId: Int64)
|
||||
case apiSetProfileAddress(userId: Int64, on: Bool)
|
||||
case apiSetAddressSettings(userId: Int64, addressSettings: AddressSettings)
|
||||
case apiSetUserName(userId: Int64, name: String?)
|
||||
case apiVerifyContactName(contactId: Int64)
|
||||
case apiVerifyPublicGroupName(groupId: Int64)
|
||||
case apiSetUserDomain(userId: Int64, simplexDomain: String?)
|
||||
case apiVerifyContactDomain(contactId: Int64)
|
||||
case apiVerifyGroupDomain(groupId: Int64)
|
||||
case apiAcceptContact(incognito: Bool, contactReqId: Int64)
|
||||
case apiRejectContact(contactReqId: Int64)
|
||||
// WebRTC calls
|
||||
@@ -374,10 +374,10 @@ enum ChatCommand: ChatCmdProtocol {
|
||||
case let .apiAddMyAddressShortLink(userId): return "/_short_link_address \(userId)"
|
||||
case let .apiSetProfileAddress(userId, on): return "/_profile_address \(userId) \(onOff(on))"
|
||||
case let .apiSetAddressSettings(userId, addressSettings): return "/_address_settings \(userId) \(encodeJSON(addressSettings))"
|
||||
case let .apiSetUserName(userId, name): return "/_set_name \(userId)" + (name.map { " " + $0 } ?? "")
|
||||
case let .apiSetUserDomain(userId, simplexDomain): return "/_set domain \(userId)" + (simplexDomain.map { " " + $0 } ?? "")
|
||||
case let .apiSetPublicGroupAccess(groupId, access): return "/_public group access #\(groupId) \(encodeJSON(access))"
|
||||
case let .apiVerifyContactName(contactId): return "/_verify name @\(contactId)"
|
||||
case let .apiVerifyPublicGroupName(groupId): return "/_verify name #\(groupId)"
|
||||
case let .apiVerifyContactDomain(contactId): return "/_verify domain @\(contactId)"
|
||||
case let .apiVerifyGroupDomain(groupId): return "/_verify domain #\(groupId)"
|
||||
case let .apiAcceptContact(incognito, contactReqId): return "/_accept incognito=\(onOff(incognito)) \(contactReqId)"
|
||||
case let .apiRejectContact(contactReqId): return "/_reject \(contactReqId)"
|
||||
case let .apiSendCallInvitation(contact, callType): return "/_call invite @\(contact.apiId) \(encodeJSON(callType))"
|
||||
@@ -560,9 +560,9 @@ enum ChatCommand: ChatCmdProtocol {
|
||||
case .apiAddMyAddressShortLink: return "apiAddMyAddressShortLink"
|
||||
case .apiSetProfileAddress: return "apiSetProfileAddress"
|
||||
case .apiSetAddressSettings: return "apiSetAddressSettings"
|
||||
case .apiSetUserName: return "apiSetUserName"
|
||||
case .apiVerifyContactName: return "apiVerifyContactName"
|
||||
case .apiVerifyPublicGroupName: return "apiVerifyPublicGroupName"
|
||||
case .apiSetUserDomain: return "apiSetUserDomain"
|
||||
case .apiVerifyContactDomain: return "apiVerifyContactDomain"
|
||||
case .apiVerifyGroupDomain: return "apiVerifyGroupDomain"
|
||||
case .apiAcceptContact: return "apiAcceptContact"
|
||||
case .apiRejectContact: return "apiRejectContact"
|
||||
case .apiSendCallInvitation: return "apiSendCallInvitation"
|
||||
|
||||
@@ -1083,17 +1083,17 @@ private func apiConnectResponseAlert<R>(_ r: APIResult<R>) -> Alert {
|
||||
title: "Unsupported connection link",
|
||||
message: "This link requires a newer app version. Please upgrade the app or ask your contact to send a compatible link."
|
||||
)
|
||||
case let .error(.simplexName(name, err)):
|
||||
case let .error(.simplexDomain(domain, err)):
|
||||
switch err {
|
||||
case .noValidLink:
|
||||
mkAlert(
|
||||
title: "No valid link",
|
||||
message: "The SimpleX name \(name.shortName) is registered, but it has no valid link."
|
||||
message: "The SimpleX name \(domain.fullDomainName) is registered, but it has no valid link."
|
||||
)
|
||||
case .unknownName:
|
||||
case .unknownDomain:
|
||||
mkAlert(
|
||||
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."
|
||||
message: "The SimpleX name \(domain.fullDomainName) 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):
|
||||
@@ -1368,19 +1368,19 @@ func apiSetProfileAddress(on: Bool) async throws -> User? {
|
||||
// name is the encoded SimplexName (e.g. "@alice.simplex"); nil clears it
|
||||
// owner-specific SNENoValidLink wording; everything else reuses the general apiConnectResponseAlert
|
||||
func showSetSimplexNameError<R>(_ r: APIResult<R>, isChannel: Bool) {
|
||||
if case let .error(.simplexName(name, .noValidLink)) = r.unexpected {
|
||||
if case let .error(.simplexDomain(domain, .noValidLink)) = r.unexpected {
|
||||
let format = isChannel
|
||||
? NSLocalizedString("The SimpleX name %@ is registered without channel link. Add channel link to the name via the registration page.", comment: "alert message")
|
||||
: NSLocalizedString("The SimpleX name %@ is registered without SimpleX address. Add your SimpleX address to the name via the registration page.", comment: "alert message")
|
||||
showAlert(NSLocalizedString("Error saving name", comment: "alert title"), message: String.localizedStringWithFormat(format, name.shortName))
|
||||
? NSLocalizedString("The SimpleX name #%@ is registered without channel link. Add channel link to the name via the registration page.", comment: "alert message")
|
||||
: NSLocalizedString("The SimpleX name @%@ is registered without SimpleX address. Add your SimpleX address to the name via the registration page.", comment: "alert message")
|
||||
showAlert(NSLocalizedString("Error saving name", comment: "alert title"), message: String.localizedStringWithFormat(format, domain.fullDomainName))
|
||||
} else {
|
||||
AlertManager.shared.showAlert(apiConnectResponseAlert(r))
|
||||
}
|
||||
}
|
||||
|
||||
func apiSetUserName(_ name: String?) async throws -> User {
|
||||
let userId = try currentUserId("apiSetUserName")
|
||||
let r: APIResult<ChatResponse1> = await chatApiSendCmd(.apiSetUserName(userId: userId, name: name))
|
||||
func apiSetUserDomain(_ simplexDomain: String?) async throws -> User {
|
||||
let userId = try currentUserId("apiSetUserDomain")
|
||||
let r: APIResult<ChatResponse1> = await chatApiSendCmd(.apiSetUserDomain(userId: userId, simplexDomain: simplexDomain))
|
||||
switch r {
|
||||
case let .result(.userProfileUpdated(user, _, _, _)): return user
|
||||
case let .result(.userProfileNoChange(user)): return user
|
||||
@@ -1390,14 +1390,14 @@ func apiSetUserName(_ name: String?) async throws -> User {
|
||||
}
|
||||
}
|
||||
|
||||
func apiVerifyContactName(_ contactId: Int64) async throws -> (Contact, String?) {
|
||||
let r: ChatResponse2 = try await chatSendCmd(.apiVerifyContactName(contactId: contactId))
|
||||
func apiVerifyContactDomain(_ contactId: Int64) async throws -> (Contact, String?) {
|
||||
let r: ChatResponse2 = try await chatSendCmd(.apiVerifyContactDomain(contactId: contactId))
|
||||
if case let .contactNameVerified(_, contact, verificationFailure) = r { return (contact, verificationFailure) }
|
||||
throw r.unexpected
|
||||
}
|
||||
|
||||
func apiVerifyPublicGroupName(_ groupId: Int64) async throws -> (GroupInfo, String?) {
|
||||
let r: ChatResponse2 = try await chatSendCmd(.apiVerifyPublicGroupName(groupId: groupId))
|
||||
func apiVerifyGroupDomain(_ groupId: Int64) async throws -> (GroupInfo, String?) {
|
||||
let r: ChatResponse2 = try await chatSendCmd(.apiVerifyGroupDomain(groupId: groupId))
|
||||
if case let .groupNameVerified(_, groupInfo, verificationFailure) = r { return (groupInfo, verificationFailure) }
|
||||
throw r.unexpected
|
||||
}
|
||||
|
||||
@@ -392,21 +392,21 @@ struct ChatInfoView: View {
|
||||
.lineLimit(3)
|
||||
.padding(.bottom, 2)
|
||||
}
|
||||
if let claim = contact.profile.simplexName, contact.profile.simplexNameVerification != nil || claim.proof != nil {
|
||||
if let claim = contact.profile.contactDomain, contact.profile.contactDomainVerified != nil || claim.proof != nil {
|
||||
SimplexNameView(
|
||||
name: claim.shortName,
|
||||
verification: contact.profile.simplexNameVerification,
|
||||
verification: contact.profile.contactDomainVerified,
|
||||
autoVerify: UserDefaults.standard.bool(forKey: DEFAULT_PRIVACY_VERIFY_SIMPLEX_NAMES),
|
||||
verify: {
|
||||
do {
|
||||
let (ct, reason) = try await apiVerifyContactName(contact.contactId)
|
||||
let (ct, reason) = try await apiVerifyContactDomain(contact.contactId)
|
||||
await MainActor.run {
|
||||
chatModel.updateContact(ct)
|
||||
contact = ct
|
||||
}
|
||||
return (ct.profile.simplexNameVerification, reason)
|
||||
return (ct.profile.contactDomainVerified, reason)
|
||||
} catch {
|
||||
logger.error("apiVerifyContactName: \(responseError(error))")
|
||||
logger.error("apiVerifyContactDomain: \(responseError(error))")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ struct ChannelWebAccessView: View {
|
||||
let existingAccess = pg.publicGroupAccess
|
||||
pg.publicGroupAccess = PublicGroupAccess(
|
||||
groupWebPage: trimmedPage.isEmpty ? nil : trimmedPage,
|
||||
simplexName: existingAccess?.simplexName,
|
||||
groupDomainClaim: existingAccess?.groupDomainClaim,
|
||||
domainWebPage: existingAccess?.domainWebPage ?? false,
|
||||
allowEmbedding: allowEmbedding
|
||||
)
|
||||
|
||||
@@ -253,11 +253,11 @@ struct GroupChatInfoView: View {
|
||||
titleKey: "SimpleX name",
|
||||
footer: "Let people join via name registered with this channel link.",
|
||||
prefix: "#",
|
||||
nameText: groupInfo.groupProfile.publicGroup?.publicGroupAccess?.simplexName?.shortName ?? "",
|
||||
nameText: groupInfo.groupProfile.publicGroup?.publicGroupAccess?.groupDomainClaim?.shortName ?? "",
|
||||
save: { name in
|
||||
do {
|
||||
var access = groupInfo.groupProfile.publicGroup?.publicGroupAccess ?? PublicGroupAccess()
|
||||
access.simplexName = name.map { SimplexNameClaim(name: $0) }
|
||||
access.groupDomainClaim = name.map { SimplexDomainClaim(name: $0) }
|
||||
let gInfo = try await apiSetPublicGroupAccess(groupInfo.groupId, access: access)
|
||||
await MainActor.run {
|
||||
chatModel.updateGroup(gInfo)
|
||||
@@ -358,22 +358,22 @@ struct GroupChatInfoView: View {
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
if let access = groupInfo.groupProfile.publicGroup?.publicGroupAccess,
|
||||
let groupName = access.simplexName?.shortName,
|
||||
groupInfo.simplexNameVerification != nil || access.simplexName?.proof != nil {
|
||||
let groupName = access.groupDomainClaim?.shortName,
|
||||
groupInfo.groupDomainVerified != nil || access.groupDomainClaim?.proof != nil {
|
||||
SimplexNameView(
|
||||
name: groupName,
|
||||
verification: groupInfo.simplexNameVerification,
|
||||
verification: groupInfo.groupDomainVerified,
|
||||
autoVerify: UserDefaults.standard.bool(forKey: DEFAULT_PRIVACY_VERIFY_SIMPLEX_NAMES),
|
||||
verify: {
|
||||
do {
|
||||
let (gInfo, reason) = try await apiVerifyPublicGroupName(groupInfo.groupId)
|
||||
let (gInfo, reason) = try await apiVerifyGroupDomain(groupInfo.groupId)
|
||||
await MainActor.run {
|
||||
chatModel.updateGroup(gInfo)
|
||||
groupInfo = gInfo
|
||||
}
|
||||
return (gInfo.simplexNameVerification, reason)
|
||||
return (gInfo.groupDomainVerified, reason)
|
||||
} catch {
|
||||
logger.error("apiVerifyPublicGroupName: \(responseError(error))")
|
||||
logger.error("apiVerifyGroupDomain: \(responseError(error))")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,10 +197,10 @@ struct UserAddressView: View {
|
||||
titleKey: "Your SimpleX name",
|
||||
footer: "Let people connect to you via name registered with your SimpleX address.",
|
||||
prefix: "@",
|
||||
nameText: chatModel.currentUser?.profile.simplexName?.shortName ?? "",
|
||||
save: { name in
|
||||
nameText: chatModel.currentUser?.profile.contactDomain?.shortName ?? "",
|
||||
save: { simplexDomain in
|
||||
do {
|
||||
let u = try await apiSetUserName(name)
|
||||
let u = try await apiSetUserDomain(simplexDomain)
|
||||
await MainActor.run { chatModel.updateUser(u) }
|
||||
return true
|
||||
} catch {
|
||||
@@ -754,12 +754,11 @@ struct SetSimplexNameView: View {
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
}
|
||||
|
||||
// ensure the correct type prefix so a contact name is not parsed as a group (or vice versa)
|
||||
private func normalized() -> String? {
|
||||
let s = nameText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if s.isEmpty { return nil }
|
||||
if s.hasPrefix("@") || s.hasPrefix("#") { return prefix + s.dropFirst() }
|
||||
return prefix + s
|
||||
if s.hasPrefix("@") || s.hasPrefix("#") { return String(s.dropFirst()) }
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,8 +183,8 @@
|
||||
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
|
||||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; };
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; };
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv-ghc9.6.3.a */; };
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv.a */; };
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z-ghc9.6.3.a */; };
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z.a */; };
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; };
|
||||
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
|
||||
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
|
||||
@@ -563,8 +563,8 @@
|
||||
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; };
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
|
||||
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv.a"; sourceTree = "<group>"; };
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z-ghc9.6.3.a"; sourceTree = "<group>"; };
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z.a"; sourceTree = "<group>"; };
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
|
||||
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
|
||||
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; };
|
||||
@@ -735,8 +735,8 @@
|
||||
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
|
||||
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
|
||||
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv-ghc9.6.3.a in Frameworks */,
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv.a in Frameworks */,
|
||||
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z-ghc9.6.3.a in Frameworks */,
|
||||
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z.a in Frameworks */,
|
||||
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -822,8 +822,8 @@
|
||||
64C829992D54AEEE006B9E89 /* libffi.a */,
|
||||
64C829982D54AEED006B9E89 /* libgmp.a */,
|
||||
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv-ghc9.6.3.a */,
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-IDb07VxlHBtGmeucUQceZv.a */,
|
||||
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z-ghc9.6.3.a */,
|
||||
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-7.0.0.6-67j0xDFDAaz6bMQcxTdG4Z.a */,
|
||||
);
|
||||
path = Libraries;
|
||||
sourceTree = "<group>";
|
||||
|
||||
@@ -758,7 +758,7 @@ public enum ChatErrorType: Decodable, Hashable {
|
||||
case chatNotStopped
|
||||
case chatStoreChanged
|
||||
case invalidConnReq
|
||||
case simplexName(simplexName: SimplexNameInfo, simplexNameError: SimplexNameError)
|
||||
case simplexDomain(simplexDomain: SimplexDomain, simplexDomainError: SimplexDomainError)
|
||||
case unsupportedConnReq
|
||||
case invalidChatMessage(connection: Connection, message: String)
|
||||
case connReqMessageProhibited
|
||||
|
||||
@@ -162,8 +162,8 @@ public struct LocalProfile: Codable, NamedChat, Hashable {
|
||||
peerType: ChatPeerType? = nil,
|
||||
localBadge: LocalBadge? = nil,
|
||||
localAlias: String,
|
||||
simplexName: SimplexNameClaim? = nil,
|
||||
simplexNameVerification: Bool? = nil
|
||||
contactDomain: SimplexDomainClaim? = nil,
|
||||
contactDomainVerified: Bool? = nil
|
||||
) {
|
||||
self.profileId = profileId
|
||||
self.displayName = displayName
|
||||
@@ -175,8 +175,8 @@ public struct LocalProfile: Codable, NamedChat, Hashable {
|
||||
self.peerType = peerType
|
||||
self.localBadge = localBadge
|
||||
self.localAlias = localAlias
|
||||
self.simplexName = simplexName
|
||||
self.simplexNameVerification = simplexNameVerification
|
||||
self.contactDomain = contactDomain
|
||||
self.contactDomainVerified = contactDomainVerified
|
||||
}
|
||||
|
||||
public var profileId: Int64
|
||||
@@ -189,8 +189,8 @@ public struct LocalProfile: Codable, NamedChat, Hashable {
|
||||
public var peerType: ChatPeerType?
|
||||
public var localBadge: LocalBadge?
|
||||
public var localAlias: String
|
||||
public var simplexName: SimplexNameClaim?
|
||||
public var simplexNameVerification: Bool?
|
||||
public var contactDomain: SimplexDomainClaim?
|
||||
public var contactDomainVerified: 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 simplexNameVerification: Bool?
|
||||
public var groupDomainVerified: Bool?
|
||||
|
||||
public var isOwner: Bool {
|
||||
return membership.memberRole == .owner && membership.memberCurrent
|
||||
@@ -2621,35 +2621,35 @@ public enum GroupType: Codable, Hashable {
|
||||
}
|
||||
|
||||
public struct PublicGroupAccess: Codable, Hashable {
|
||||
public init(groupWebPage: String? = nil, simplexName: SimplexNameClaim? = nil, domainWebPage: Bool = false, allowEmbedding: Bool = false) {
|
||||
public init(groupWebPage: String? = nil, groupDomainClaim: SimplexDomainClaim? = nil, domainWebPage: Bool = false, allowEmbedding: Bool = false) {
|
||||
self.groupWebPage = groupWebPage
|
||||
self.simplexName = simplexName
|
||||
self.groupDomainClaim = groupDomainClaim
|
||||
self.domainWebPage = domainWebPage
|
||||
self.allowEmbedding = allowEmbedding
|
||||
}
|
||||
|
||||
public var groupWebPage: String?
|
||||
public var simplexName: SimplexNameClaim?
|
||||
public var groupDomainClaim: SimplexDomainClaim?
|
||||
public var domainWebPage: Bool = false
|
||||
public var allowEmbedding: Bool = false
|
||||
}
|
||||
|
||||
public struct SimplexNameClaim: Codable, Hashable {
|
||||
public init(name: String, proof: NameClaimProof? = nil) {
|
||||
public struct SimplexDomainClaim: Codable, Hashable {
|
||||
public init(name: String, proof: SimplexDomainProof? = nil) {
|
||||
self.name = name
|
||||
self.proof = proof
|
||||
}
|
||||
public var name: String
|
||||
public var proof: NameClaimProof?
|
||||
public var proof: SimplexDomainProof?
|
||||
|
||||
public var shortName: String {
|
||||
name.hasPrefix("simplex:/name") ? String(name.dropFirst("simplex:/name".count)) : name
|
||||
}
|
||||
}
|
||||
|
||||
public enum SimplexNameError: Decodable, Hashable {
|
||||
public enum SimplexDomainError: Decodable, Hashable {
|
||||
case noValidLink
|
||||
case unknownName
|
||||
case unknownDomain
|
||||
}
|
||||
|
||||
public struct RelayCapabilities: Codable, Hashable {
|
||||
@@ -5285,7 +5285,7 @@ public enum SimplexLinkType: String, Decodable, Hashable {
|
||||
|
||||
public struct SimplexNameInfo: Codable, Equatable, Hashable {
|
||||
public var nameType: SimplexNameType
|
||||
public var nameDomain: SimplexNameDomain
|
||||
public var nameDomain: SimplexDomain
|
||||
|
||||
// prefix-less domain for prefilling the set-name field (mirrors shortName without the @/# prefix)
|
||||
public var editDomain: String {
|
||||
@@ -5300,13 +5300,13 @@ public struct SimplexNameInfo: Codable, Equatable, Hashable {
|
||||
(nameType == .publicGroup ? "#" : "@") + editDomain
|
||||
}
|
||||
|
||||
public init(nameType: SimplexNameType, nameDomain: SimplexNameDomain) {
|
||||
public init(nameType: SimplexNameType, nameDomain: SimplexDomain) {
|
||||
self.nameType = nameType
|
||||
self.nameDomain = nameDomain
|
||||
}
|
||||
}
|
||||
|
||||
public struct SimplexNameDomain: Codable, Equatable, Hashable {
|
||||
public struct SimplexDomain: Codable, Equatable, Hashable {
|
||||
public var nameTLD: SimplexTLD
|
||||
public var domain: String
|
||||
public var subDomain: [String]
|
||||
@@ -5340,11 +5340,10 @@ public enum SimplexNameType: String, Codable, Hashable {
|
||||
case contact
|
||||
}
|
||||
|
||||
// peer's signed name claim; UI only checks presence
|
||||
public struct NameClaimProof: Codable, Hashable {
|
||||
public struct SimplexDomainProof: Codable, Hashable {
|
||||
public var linkOwnerId: String?
|
||||
public var presHeader: String
|
||||
public var signature: String
|
||||
public var linkOwnerId: String?
|
||||
}
|
||||
|
||||
public enum FormatColor: String, Decodable, Hashable {
|
||||
|
||||
+12
-11
@@ -2039,7 +2039,8 @@ data class Profile(
|
||||
val peerType: ChatPeerType? = null,
|
||||
// the badge proof from the wire profile: not interpreted by the UI (display uses crypto-free LocalBadge),
|
||||
// but preserved so passing a link profile back to the core (apiPrepareContact) keeps the proof
|
||||
val badge: BadgeProof? = null
|
||||
val badge: BadgeProof? = null,
|
||||
val contactDomain: SimplexDomainClaim? = null
|
||||
): NamedChat {
|
||||
val profileViewName: String
|
||||
get() {
|
||||
@@ -2069,12 +2070,12 @@ data class LocalProfile(
|
||||
val preferences: ChatPreferences? = null,
|
||||
val peerType: ChatPeerType? = null,
|
||||
val localBadge: LocalBadge? = null,
|
||||
val simplexName: SimplexNameClaim? = null,
|
||||
val simplexNameVerification: Boolean? = null
|
||||
val contactDomain: SimplexDomainClaim? = null,
|
||||
val contactDomainVerified: Boolean? = null
|
||||
): NamedChat {
|
||||
val profileViewName: String = localAlias.ifEmpty { if (fullName == "" || displayName == fullName) displayName else "$displayName ($fullName)" }
|
||||
|
||||
fun toProfile(): Profile = Profile(displayName, fullName, shortDescr, image, localAlias, contactLink, preferences, peerType)
|
||||
fun toProfile(): Profile = Profile(displayName, fullName, shortDescr, image, localAlias, contactLink, preferences, peerType, contactDomain = contactDomain)
|
||||
|
||||
companion object {
|
||||
val sampleData = LocalProfile(
|
||||
@@ -2200,7 +2201,7 @@ data class GroupInfo (
|
||||
val chatTags: List<Long>,
|
||||
val chatItemTTL: Long?,
|
||||
override val localAlias: String,
|
||||
val simplexNameVerification: Boolean? = null,
|
||||
val groupDomainVerified: Boolean? = null,
|
||||
): SomeChat, NamedChat {
|
||||
override val chatType get() = ChatType.Group
|
||||
override val id get() = "#$groupId"
|
||||
@@ -2323,9 +2324,9 @@ object GroupTypeSerializer : KSerializer<GroupType> {
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class SimplexNameClaim(
|
||||
data class SimplexDomainClaim(
|
||||
val name: String,
|
||||
val proof: NameClaimProof? = null
|
||||
val proof: SimplexDomainProof? = null
|
||||
) {
|
||||
val shortName: String get() = name.removePrefix("simplex:/name")
|
||||
}
|
||||
@@ -2333,7 +2334,7 @@ data class SimplexNameClaim(
|
||||
@Serializable
|
||||
data class PublicGroupAccess(
|
||||
val groupWebPage: String? = null,
|
||||
val simplexName: SimplexNameClaim? = null,
|
||||
val groupDomainClaim: SimplexDomainClaim? = null,
|
||||
val domainWebPage: Boolean = false,
|
||||
val allowEmbedding: Boolean = false
|
||||
)
|
||||
@@ -4885,7 +4886,7 @@ enum class SimplexLinkType(val linkType: String) {
|
||||
@Serializable
|
||||
data class SimplexNameInfo(
|
||||
val nameType: SimplexNameType,
|
||||
val nameDomain: SimplexNameDomain
|
||||
val nameDomain: SimplexDomain
|
||||
) {
|
||||
// prefix-less domain for prefilling the set-name field (shortName without the @/# prefix)
|
||||
val editDomain: String
|
||||
@@ -4899,7 +4900,7 @@ data class SimplexNameInfo(
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class SimplexNameDomain(
|
||||
data class SimplexDomain(
|
||||
val nameTLD: SimplexTLD,
|
||||
val domain: String,
|
||||
val subDomain: List<String>
|
||||
@@ -4931,7 +4932,7 @@ enum class SimplexNameType {
|
||||
|
||||
// peer's signed name claim; UI only checks presence
|
||||
@Serializable
|
||||
data class NameClaimProof(
|
||||
data class SimplexDomainProof(
|
||||
val presHeader: String,
|
||||
val signature: String,
|
||||
val linkOwnerId: String? = null
|
||||
|
||||
+34
-34
@@ -1558,17 +1558,17 @@ object ChatController {
|
||||
)
|
||||
}
|
||||
r is API.Error && r.err is ChatError.ChatErrorChat
|
||||
&& r.err.errorType is ChatErrorType.SimplexName -> {
|
||||
val name = r.err.errorType.simplexName.shortName
|
||||
if (r.err.errorType.simplexNameError is SimplexNameError.NoValidLink) {
|
||||
&& r.err.errorType is ChatErrorType.CESimplexDomain -> {
|
||||
val domain = r.err.errorType.simplexDomain.fullDomainName
|
||||
if (r.err.errorType.simplexDomainError is SimplexDomainError.NoValidLink) {
|
||||
AlertManager.shared.showAlertMsg(
|
||||
generalGetString(MR.strings.simplex_name_no_valid_link),
|
||||
generalGetString(MR.strings.simplex_name_no_valid_link_desc).format(name)
|
||||
generalGetString(MR.strings.simplex_name_no_valid_link_desc).format(domain)
|
||||
)
|
||||
} else {
|
||||
AlertManager.shared.showAlertMsg(
|
||||
generalGetString(MR.strings.simplex_name_unconfirmed),
|
||||
generalGetString(MR.strings.simplex_name_unconfirmed_desc).format(name)
|
||||
generalGetString(MR.strings.simplex_name_unconfirmed_desc).format(domain)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1631,10 +1631,10 @@ object ChatController {
|
||||
|
||||
// owner-specific wording for setting one's own/channel name; null for other errors (handled by apiConnectResponseAlert)
|
||||
fun simplexNameOwnerError(err: ChatError, isChannel: Boolean): String? =
|
||||
if (err is ChatError.ChatErrorChat && err.errorType is ChatErrorType.SimplexName && err.errorType.simplexNameError is SimplexNameError.NoValidLink) {
|
||||
val name = err.errorType.simplexName.shortName
|
||||
if (isChannel) generalGetString(MR.strings.simplex_name_owner_no_channel_link).format(name)
|
||||
else generalGetString(MR.strings.simplex_name_owner_no_address).format(name)
|
||||
if (err is ChatError.ChatErrorChat && err.errorType is ChatErrorType.CESimplexDomain && err.errorType.simplexDomainError is SimplexDomainError.NoValidLink) {
|
||||
val domain = err.errorType.simplexDomain.fullDomainName
|
||||
if (isChannel) generalGetString(MR.strings.simplex_name_owner_no_channel_link).format(domain)
|
||||
else generalGetString(MR.strings.simplex_name_owner_no_address).format(domain)
|
||||
} else null
|
||||
|
||||
fun connErrorText(e: ChatError): String = when {
|
||||
@@ -1642,8 +1642,8 @@ object ChatController {
|
||||
generalGetString(MR.strings.invalid_connection_link)
|
||||
e is ChatError.ChatErrorChat && e.errorType is ChatErrorType.UnsupportedConnReq ->
|
||||
generalGetString(MR.strings.unsupported_connection_link)
|
||||
e is ChatError.ChatErrorChat && e.errorType is ChatErrorType.SimplexName ->
|
||||
if (e.errorType.simplexNameError is SimplexNameError.NoValidLink)
|
||||
e is ChatError.ChatErrorChat && e.errorType is ChatErrorType.CESimplexDomain ->
|
||||
if (e.errorType.simplexDomainError is SimplexDomainError.NoValidLink)
|
||||
generalGetString(MR.strings.simplex_name_no_valid_link)
|
||||
else generalGetString(MR.strings.simplex_name_unconfirmed)
|
||||
e is ChatError.ChatErrorAgent && e.agentError is AgentErrorType.NO_NAME_SERVERS ->
|
||||
@@ -1823,9 +1823,9 @@ object ChatController {
|
||||
}
|
||||
|
||||
// name is the encoded SimplexName (e.g. "@alice.simplex"); null clears it. Throws on rejection.
|
||||
suspend fun apiSetUserName(rh: Long?, name: String?): User {
|
||||
val userId = currentUserId("apiSetUserName")
|
||||
val r = sendCmd(rh, CC.ApiSetUserName(userId, name))
|
||||
suspend fun apiSetUserDomain(rh: Long?, simplexDomain: String?): User {
|
||||
val userId = currentUserId("apiSetUserDomain")
|
||||
val r = sendCmd(rh, CC.ApiSetUserDomain(userId, simplexDomain))
|
||||
return when {
|
||||
r is API.Result && r.res is CR.UserProfileUpdated -> r.res.user.updateRemoteHostId(rh)
|
||||
r is API.Result && r.res is CR.UserProfileNoChange -> r.res.user.updateRemoteHostId(rh)
|
||||
@@ -1840,17 +1840,17 @@ object ChatController {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun apiVerifyContactName(rh: Long?, contactId: Long): Pair<Contact, String?>? {
|
||||
val r = sendCmd(rh, CC.ApiVerifyContactName(contactId))
|
||||
suspend fun apiVerifyContactDomain(rh: Long?, contactId: Long): Pair<Contact, String?>? {
|
||||
val r = sendCmd(rh, CC.ApiVerifyContactDomain(contactId))
|
||||
if (r is API.Result && r.res is CR.ContactNameVerified) return r.res.contact to r.res.verificationFailure
|
||||
Log.e(TAG, "apiVerifyContactName bad response: ${r.responseType} ${r.details}")
|
||||
Log.e(TAG, "apiVerifyContactDomain bad response: ${r.responseType} ${r.details}")
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun apiVerifyPublicGroupName(rh: Long?, groupId: Long): Pair<GroupInfo, String?>? {
|
||||
val r = sendCmd(rh, CC.ApiVerifyPublicGroupName(groupId))
|
||||
suspend fun apiVerifyGroupDomain(rh: Long?, groupId: Long): Pair<GroupInfo, String?>? {
|
||||
val r = sendCmd(rh, CC.ApiVerifyGroupDomain(groupId))
|
||||
if (r is API.Result && r.res is CR.GroupNameVerified) return r.res.groupInfo to r.res.verificationFailure
|
||||
Log.e(TAG, "apiVerifyPublicGroupName bad response: ${r.responseType} ${r.details}")
|
||||
Log.e(TAG, "apiVerifyGroupDomain bad response: ${r.responseType} ${r.details}")
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -3885,9 +3885,9 @@ sealed class CC {
|
||||
class ApiShowMyAddress(val userId: Long): CC()
|
||||
class ApiAddMyAddressShortLink(val userId: Long): CC()
|
||||
class ApiSetProfileAddress(val userId: Long, val on: Boolean): CC()
|
||||
class ApiSetUserName(val userId: Long, val name: String?): CC()
|
||||
class ApiVerifyContactName(val contactId: Long): CC()
|
||||
class ApiVerifyPublicGroupName(val groupId: Long): CC()
|
||||
class ApiSetUserDomain(val userId: Long, val simplexDomain: String?): CC()
|
||||
class ApiVerifyContactDomain(val contactId: Long): CC()
|
||||
class ApiVerifyGroupDomain(val groupId: Long): CC()
|
||||
class ApiSetAddressSettings(val userId: Long, val addressSettings: AddressSettings): CC()
|
||||
class ApiGetCallInvitations: CC()
|
||||
class ApiSendCallInvitation(val contact: Contact, val callType: CallType): CC()
|
||||
@@ -4096,10 +4096,10 @@ sealed class CC {
|
||||
is ApiShowMyAddress -> "/_show_address $userId"
|
||||
is ApiAddMyAddressShortLink -> "/_short_link_address $userId"
|
||||
is ApiSetProfileAddress -> "/_profile_address $userId ${onOff(on)}"
|
||||
is ApiSetUserName -> "/_set_name $userId" + (if (name != null) " $name" else "")
|
||||
is ApiSetUserDomain -> "/_set domain $userId" + (if (simplexDomain != null) " $simplexDomain" else "")
|
||||
is ApiSetPublicGroupAccess -> "/_public group access #$groupId ${json.encodeToString(access)}"
|
||||
is ApiVerifyContactName -> "/_verify name @$contactId"
|
||||
is ApiVerifyPublicGroupName -> "/_verify name #$groupId"
|
||||
is ApiVerifyContactDomain -> "/_verify domain @$contactId"
|
||||
is ApiVerifyGroupDomain -> "/_verify domain #$groupId"
|
||||
is ApiSetAddressSettings -> "/_address_settings $userId ${json.encodeToString(addressSettings)}"
|
||||
is ApiAcceptContact -> "/_accept incognito=${onOff(incognito)} $contactReqId"
|
||||
is ApiRejectContact -> "/_reject $contactReqId"
|
||||
@@ -4281,10 +4281,10 @@ sealed class CC {
|
||||
is ApiShowMyAddress -> "apiShowMyAddress"
|
||||
is ApiAddMyAddressShortLink -> "apiAddMyAddressShortLink"
|
||||
is ApiSetProfileAddress -> "apiSetProfileAddress"
|
||||
is ApiSetUserName -> "apiSetUserName"
|
||||
is ApiSetUserDomain -> "apiSetUserDomain"
|
||||
is ApiSetPublicGroupAccess -> "apiSetPublicGroupAccess"
|
||||
is ApiVerifyContactName -> "apiVerifyContactName"
|
||||
is ApiVerifyPublicGroupName -> "apiVerifyPublicGroupName"
|
||||
is ApiVerifyContactDomain -> "apiVerifyContactDomain"
|
||||
is ApiVerifyGroupDomain -> "apiVerifyGroupDomain"
|
||||
is ApiSetAddressSettings -> "apiSetAddressSettings"
|
||||
is ApiAcceptContact -> "apiAcceptContact"
|
||||
is ApiRejectContact -> "apiRejectContact"
|
||||
@@ -7096,9 +7096,9 @@ sealed class OwnerVerification {
|
||||
}
|
||||
|
||||
@Serializable
|
||||
sealed class SimplexNameError {
|
||||
@Serializable @SerialName("noValidLink") object NoValidLink : SimplexNameError()
|
||||
@Serializable @SerialName("unknownName") object UnknownName : SimplexNameError()
|
||||
sealed class SimplexDomainError {
|
||||
@Serializable @SerialName("noValidLink") object NoValidLink : SimplexDomainError()
|
||||
@Serializable @SerialName("unknownDomain") object UnknownDomain : SimplexDomainError()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@@ -7438,7 +7438,7 @@ sealed class ChatErrorType {
|
||||
is ChatStoreChanged -> "chatStoreChanged"
|
||||
is ConnectionPlanChatError -> "connectionPlan"
|
||||
is InvalidConnReq -> "invalidConnReq"
|
||||
is SimplexName -> "simplexName"
|
||||
is CESimplexDomain -> "simplexDomain"
|
||||
is UnsupportedConnReq -> "unsupportedConnReq"
|
||||
is InvalidChatMessage -> "invalidChatMessage"
|
||||
is ConnReqMessageProhibited -> "connReqMessageProhibited"
|
||||
@@ -7521,7 +7521,7 @@ sealed class ChatErrorType {
|
||||
@Serializable @SerialName("chatStoreChanged") object ChatStoreChanged: ChatErrorType()
|
||||
@Serializable @SerialName("connectionPlan") class ConnectionPlanChatError(val connectionPlan: ConnectionPlan): ChatErrorType()
|
||||
@Serializable @SerialName("invalidConnReq") object InvalidConnReq: ChatErrorType()
|
||||
@Serializable @SerialName("simplexName") class SimplexName(val simplexName: SimplexNameInfo, val simplexNameError: SimplexNameError): ChatErrorType()
|
||||
@Serializable @SerialName("simplexDomain") class CESimplexDomain(val simplexDomain: SimplexDomain, val simplexDomainError: SimplexDomainError): ChatErrorType()
|
||||
@Serializable @SerialName("unsupportedConnReq") object UnsupportedConnReq: ChatErrorType()
|
||||
@Serializable @SerialName("invalidChatMessage") class InvalidChatMessage(val connection: Connection, val message: String): ChatErrorType()
|
||||
@Serializable @SerialName("connReqMessageProhibited") object ConnReqMessageProhibited: ChatErrorType()
|
||||
|
||||
+6
-6
@@ -757,17 +757,17 @@ fun ChatInfoHeader(cInfo: ChatInfo, contact: Contact) {
|
||||
modifier = Modifier.combinedClickable(onClick = copyDisplayName, onLongClick = copyDisplayName).onRightClick(copyDisplayName)
|
||||
)
|
||||
ChatInfoDescription(cInfo, displayName, copyNameToClipboard)
|
||||
val simplexName = contact.profile.simplexName
|
||||
if (simplexName != null && (contact.profile.simplexNameVerification != null || simplexName.proof != null)) {
|
||||
val domain = contact.profile.contactDomain
|
||||
if (domain != null && (contact.profile.contactDomainVerified != null || domain.proof != null)) {
|
||||
SimplexNameView(
|
||||
name = simplexName.shortName,
|
||||
verification = contact.profile.simplexNameVerification,
|
||||
name = domain.shortName,
|
||||
verification = contact.profile.contactDomainVerified,
|
||||
autoVerify = chatModel.controller.appPrefs.privacyVerifySimplexNames.get(),
|
||||
verify = {
|
||||
val rhId = chatModel.remoteHostId()
|
||||
chatModel.controller.apiVerifyContactName(rhId, contact.contactId)?.let { (ct, reason) ->
|
||||
chatModel.controller.apiVerifyContactDomain(rhId, contact.contactId)?.let { (ct, reason) ->
|
||||
chatModel.chatsContext.updateContact(rhId, ct)
|
||||
ct.profile.simplexNameVerification to reason
|
||||
ct.profile.contactDomainVerified to reason
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ fun ChannelWebPageView(
|
||||
val trimmedPage = webPage.value.trim()
|
||||
val newAccess = PublicGroupAccess(
|
||||
groupWebPage = trimmedPage.ifEmpty { null },
|
||||
simplexName = access?.simplexName,
|
||||
groupDomainClaim = access?.groupDomainClaim,
|
||||
domainWebPage = access?.domainWebPage ?: false,
|
||||
allowEmbedding = allowEmbedding.value
|
||||
)
|
||||
|
||||
+8
-8
@@ -184,10 +184,10 @@ fun ModalData.GroupChatInfoView(
|
||||
title = generalGetString(MR.strings.set_simplex_name),
|
||||
footer = generalGetString(MR.strings.set_channel_simplex_name_footer),
|
||||
prefix = "#",
|
||||
initial = groupInfo.groupProfile.publicGroup?.publicGroupAccess?.simplexName?.shortName ?: "",
|
||||
initial = groupInfo.groupProfile.publicGroup?.publicGroupAccess?.groupDomainClaim?.shortName ?: "",
|
||||
save = { name ->
|
||||
val access = groupInfo.groupProfile.publicGroup?.publicGroupAccess ?: PublicGroupAccess()
|
||||
val newAccess = access.copy(simplexName = name?.let { SimplexNameClaim(it) })
|
||||
val newAccess = access.copy(groupDomainClaim = name?.let { SimplexDomainClaim(it) })
|
||||
val gInfo = chatModel.controller.apiSetPublicGroupAccess(rhId, groupInfo.groupId, newAccess)
|
||||
if (gInfo != null) {
|
||||
withContext(Dispatchers.Main) { chatModel.chatsContext.updateGroup(rhId, gInfo) }
|
||||
@@ -975,17 +975,17 @@ private fun GroupChatInfoHeader(cInfo: ChatInfo, groupInfo: GroupInfo) {
|
||||
)
|
||||
ChatInfoDescription(cInfo, displayName, copyNameToClipboard)
|
||||
val access = groupInfo.groupProfile.publicGroup?.publicGroupAccess
|
||||
val groupName = access?.simplexName?.shortName
|
||||
if (groupName != null && (groupInfo.simplexNameVerification != null || access.simplexName?.proof != null)) {
|
||||
val domain = access?.groupDomainClaim?.shortName
|
||||
if (domain != null && (groupInfo.groupDomainVerified != null || access.groupDomainClaim?.proof != null)) {
|
||||
SimplexNameView(
|
||||
name = groupName,
|
||||
verification = groupInfo.simplexNameVerification,
|
||||
name = domain,
|
||||
verification = groupInfo.groupDomainVerified,
|
||||
autoVerify = chatModel.controller.appPrefs.privacyVerifySimplexNames.get(),
|
||||
verify = {
|
||||
val rhId = chatModel.remoteHostId()
|
||||
chatModel.controller.apiVerifyPublicGroupName(rhId, groupInfo.groupId)?.let { (gInfo, reason) ->
|
||||
chatModel.controller.apiVerifyGroupDomain(rhId, groupInfo.groupId)?.let { (gInfo, reason) ->
|
||||
chatModel.chatsContext.updateGroup(rhId, gInfo)
|
||||
gInfo.simplexNameVerification to reason
|
||||
gInfo.groupDomainVerified to reason
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
+2
-2
@@ -35,8 +35,8 @@ fun SetSimplexNameView(
|
||||
val s = name.value.trim()
|
||||
return when {
|
||||
s.isEmpty() -> null
|
||||
s.startsWith("@") || s.startsWith("#") -> prefix + s.substring(1)
|
||||
else -> prefix + s
|
||||
s.startsWith("@") || s.startsWith("#") -> s.substring(1)
|
||||
else -> s
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -373,14 +373,14 @@ private fun UserAddressLayout(
|
||||
title = generalGetString(MR.strings.set_simplex_name),
|
||||
footer = generalGetString(MR.strings.set_user_simplex_name_footer),
|
||||
prefix = "@",
|
||||
initial = user?.profile?.simplexName?.shortName ?: "",
|
||||
save = { name ->
|
||||
initial = user?.profile?.contactDomain?.shortName ?: "",
|
||||
save = { simplexDomain ->
|
||||
try {
|
||||
val u = chatModel.controller.apiSetUserName(user?.remoteHostId, name)
|
||||
val u = chatModel.controller.apiSetUserDomain(user?.remoteHostId, simplexDomain)
|
||||
withContext(Dispatchers.Main) { chatModel.updateUser(u) }
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "apiSetUserName: ${e.message}")
|
||||
Log.e(TAG, "apiSetUserDomain: ${e.message}")
|
||||
false
|
||||
}
|
||||
},
|
||||
|
||||
+56
-56
@@ -139,7 +139,6 @@ This file is generated automatically.
|
||||
- [MsgReaction](#msgreaction)
|
||||
- [MsgReceiptStatus](#msgreceiptstatus)
|
||||
- [MsgSigStatus](#msgsigstatus)
|
||||
- [NameClaimProof](#nameclaimproof)
|
||||
- [NameErrorType](#nameerrortype)
|
||||
- [NetworkError](#networkerror)
|
||||
- [NewUser](#newuser)
|
||||
@@ -174,10 +173,11 @@ This file is generated automatically.
|
||||
- [SMPAgentError](#smpagenterror)
|
||||
- [SecurityCode](#securitycode)
|
||||
- [SimplePreference](#simplepreference)
|
||||
- [SimplexDomain](#simplexdomain)
|
||||
- [SimplexDomainClaim](#simplexdomainclaim)
|
||||
- [SimplexDomainError](#simplexdomainerror)
|
||||
- [SimplexDomainProof](#simplexdomainproof)
|
||||
- [SimplexLinkType](#simplexlinktype)
|
||||
- [SimplexNameClaim](#simplexnameclaim)
|
||||
- [SimplexNameDomain](#simplexnamedomain)
|
||||
- [SimplexNameError](#simplexnameerror)
|
||||
- [SimplexNameInfo](#simplexnameinfo)
|
||||
- [SimplexNameType](#simplexnametype)
|
||||
- [SimplexTLD](#simplextld)
|
||||
@@ -1111,10 +1111,10 @@ ChatStoreChanged:
|
||||
InvalidConnReq:
|
||||
- type: "invalidConnReq"
|
||||
|
||||
SimplexName:
|
||||
- type: "simplexName"
|
||||
- simplexName: [SimplexNameInfo](#simplexnameinfo)
|
||||
- simplexNameError: [SimplexNameError](#simplexnameerror)
|
||||
SimplexDomain:
|
||||
- type: "simplexDomain"
|
||||
- simplexDomain: [SimplexDomain](#simplexdomain)
|
||||
- simplexDomainError: [SimplexDomainError](#simplexdomainerror)
|
||||
|
||||
UnsupportedConnReq:
|
||||
- type: "unsupportedConnReq"
|
||||
@@ -2347,7 +2347,7 @@ MemberSupport:
|
||||
- membersRequireAttention: int
|
||||
- viaGroupLinkUri: string?
|
||||
- groupKeys: [GroupKeys](#groupkeys)?
|
||||
- simplexNameVerification: bool?
|
||||
- groupDomainVerified: bool?
|
||||
|
||||
|
||||
---
|
||||
@@ -2772,8 +2772,8 @@ Unknown:
|
||||
- peerType: [ChatPeerType](#chatpeertype)?
|
||||
- localBadge: [LocalBadge](#localbadge)?
|
||||
- localAlias: string
|
||||
- simplexName: [SimplexNameClaim](#simplexnameclaim)?
|
||||
- simplexNameVerification: bool?
|
||||
- contactDomain: [SimplexDomainClaim](#simplexdomainclaim)?
|
||||
- contactDomainVerified: bool?
|
||||
|
||||
|
||||
---
|
||||
@@ -2949,16 +2949,6 @@ Unknown:
|
||||
- "signedNoKey"
|
||||
|
||||
|
||||
---
|
||||
|
||||
## NameClaimProof
|
||||
|
||||
**Record type**:
|
||||
- linkOwnerId: string?
|
||||
- presHeader: string
|
||||
- signature: string
|
||||
|
||||
|
||||
---
|
||||
|
||||
## NameErrorType
|
||||
@@ -3146,7 +3136,7 @@ count=<count>
|
||||
- preferences: [Preferences](#preferences)?
|
||||
- peerType: [ChatPeerType](#chatpeertype)?
|
||||
- badge: [BadgeProof](#badgeproof)?
|
||||
- simplexName: [SimplexNameClaim](#simplexnameclaim)?
|
||||
- contactDomain: [SimplexDomainClaim](#simplexdomainclaim)?
|
||||
|
||||
|
||||
---
|
||||
@@ -3195,7 +3185,7 @@ NO_SESSION:
|
||||
|
||||
**Record type**:
|
||||
- groupWebPage: string?
|
||||
- simplexName: [SimplexNameClaim](#simplexnameclaim)?
|
||||
- groupDomainClaim: [SimplexDomainClaim](#simplexdomainclaim)?
|
||||
- domainWebPage: bool
|
||||
- allowEmbedding: bool
|
||||
|
||||
@@ -3579,6 +3569,48 @@ A_QUEUE:
|
||||
- allow: [FeatureAllowed](#featureallowed)
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SimplexDomain
|
||||
|
||||
**Record type**:
|
||||
- nameTLD: [SimplexTLD](#simplextld)
|
||||
- domain: string
|
||||
- subDomain: [string]
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SimplexDomainClaim
|
||||
|
||||
**Record type**:
|
||||
- domain: string
|
||||
- proof: [SimplexDomainProof](#simplexdomainproof)?
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SimplexDomainError
|
||||
|
||||
**Discriminated union type**:
|
||||
|
||||
NoValidLink:
|
||||
- type: "noValidLink"
|
||||
|
||||
UnknownDomain:
|
||||
- type: "unknownDomain"
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SimplexDomainProof
|
||||
|
||||
**Record type**:
|
||||
- linkOwnerId: string?
|
||||
- presHeader: string
|
||||
- signature: string
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SimplexLinkType
|
||||
@@ -3591,45 +3623,13 @@ A_QUEUE:
|
||||
- "relay"
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SimplexNameClaim
|
||||
|
||||
**Record type**:
|
||||
- name: string
|
||||
- proof: [NameClaimProof](#nameclaimproof)?
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SimplexNameDomain
|
||||
|
||||
**Record type**:
|
||||
- nameTLD: [SimplexTLD](#simplextld)
|
||||
- domain: string
|
||||
- subDomain: [string]
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SimplexNameError
|
||||
|
||||
**Discriminated union type**:
|
||||
|
||||
NoValidLink:
|
||||
- type: "noValidLink"
|
||||
|
||||
UnknownName:
|
||||
- type: "unknownName"
|
||||
|
||||
|
||||
---
|
||||
|
||||
## SimplexNameInfo
|
||||
|
||||
**Record type**:
|
||||
- nameType: [SimplexNameType](#simplexnametype)
|
||||
- nameDomain: [SimplexNameDomain](#simplexnamedomain)
|
||||
- nameDomain: [SimplexDomain](#simplexdomain)
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -414,7 +414,7 @@ undocumentedCommands =
|
||||
"APISetServerOperators",
|
||||
"APISetUserContactReceipts",
|
||||
"APISetUserGroupReceipts",
|
||||
"APISetUserName",
|
||||
"APISetUserDomain",
|
||||
"APISetUserServers",
|
||||
"APISetUserUIThemes",
|
||||
"APIShareChatMsgContent",
|
||||
@@ -434,9 +434,9 @@ undocumentedCommands =
|
||||
"APIUserRead",
|
||||
"APIValidateServers",
|
||||
"APIVerifyContact",
|
||||
"APIVerifyContactName",
|
||||
"APIVerifyContactDomain",
|
||||
"APIVerifyGroupMember",
|
||||
"APIVerifyPublicGroupName",
|
||||
"APIVerifyGroupDomain",
|
||||
"APIVerifyToken",
|
||||
"CheckChatRunning",
|
||||
"ConfirmRemoteCtrl",
|
||||
|
||||
@@ -322,7 +322,6 @@ chatTypesDocsData =
|
||||
(sti @MsgReaction, STUnion, "MR", [], "", ""),
|
||||
(sti @MsgReceiptStatus, STEnum, "MR", [], "", ""),
|
||||
(sti @MsgSigStatus, STEnum, "MSS", [], "", ""),
|
||||
(sti @NameClaimProof, STRecord, "", [], "", ""),
|
||||
(sti @NameErrorType, STUnion, "", [], "", ""),
|
||||
(sti @NetworkError, STUnion, "NE", [], "", ""),
|
||||
(sti @NewUser, STRecord, "", [], "", ""),
|
||||
@@ -356,10 +355,11 @@ chatTypesDocsData =
|
||||
(sti @RoleGroupPreference, STRecord, "", [], "", ""),
|
||||
(sti @SecurityCode, STRecord, "", [], "", ""),
|
||||
(sti @SimplePreference, STRecord, "", [], "", ""),
|
||||
(sti @SimplexDomain, STRecord, "", [], "", ""),
|
||||
(sti @SimplexDomainClaim, STRecord, "", [], "", ""),
|
||||
(sti @SimplexDomainError, STUnion, "SDE", [], "", ""),
|
||||
(sti @SimplexDomainProof, STRecord, "", [], "", ""),
|
||||
(sti @SimplexLinkType, STEnum, "XL", [], "", ""),
|
||||
(sti @SimplexNameClaim, STRecord, "", [], "", ""),
|
||||
(sti @SimplexNameDomain, STRecord, "", [], "", ""),
|
||||
(sti @SimplexNameError, STUnion, "SNE", [], "", ""),
|
||||
(sti @SimplexNameInfo, STRecord, "", [], "", ""),
|
||||
(sti @SimplexNameType, STEnum, "NT", [], "", ""),
|
||||
(sti @SimplexTLD, STEnum, "TLD", [], "", ""),
|
||||
@@ -553,7 +553,6 @@ deriving instance Generic MsgFilter
|
||||
deriving instance Generic MsgReaction
|
||||
deriving instance Generic MsgReceiptStatus
|
||||
deriving instance Generic MsgSigStatus
|
||||
deriving instance Generic NameClaimProof
|
||||
deriving instance Generic NameErrorType
|
||||
deriving instance Generic NetworkError
|
||||
deriving instance Generic NewUser
|
||||
@@ -585,10 +584,11 @@ deriving instance Generic RelayProfile
|
||||
deriving instance Generic RelayStatus
|
||||
deriving instance Generic ReportReason
|
||||
deriving instance Generic SecurityCode
|
||||
deriving instance Generic SimplexDomain
|
||||
deriving instance Generic SimplexDomainClaim
|
||||
deriving instance Generic SimplexDomainError
|
||||
deriving instance Generic SimplexDomainProof
|
||||
deriving instance Generic SimplexLinkType
|
||||
deriving instance Generic SimplexNameClaim
|
||||
deriving instance Generic SimplexNameDomain
|
||||
deriving instance Generic SimplexNameError
|
||||
deriving instance Generic SimplexNameInfo
|
||||
deriving instance Generic SimplexNameType
|
||||
deriving instance Generic SimplexTLD
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ constraints: zip +disable-bzip2 +disable-zstd
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/simplex-chat/simplexmq.git
|
||||
tag: 93925b257c76ee95d9b9ea3dcf433fecdb514c9c
|
||||
tag: 836254a4c6bd5e17b40acbcaf77a83802d44919e
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
|
||||
@@ -1042,7 +1042,7 @@ export type ChatErrorType =
|
||||
| ChatErrorType.ChatNotStopped
|
||||
| ChatErrorType.ChatStoreChanged
|
||||
| ChatErrorType.InvalidConnReq
|
||||
| ChatErrorType.SimplexName
|
||||
| ChatErrorType.SimplexDomain
|
||||
| ChatErrorType.UnsupportedConnReq
|
||||
| ChatErrorType.ConnReqMessageProhibited
|
||||
| ChatErrorType.ContactNotReady
|
||||
@@ -1120,7 +1120,7 @@ export namespace ChatErrorType {
|
||||
| "chatNotStopped"
|
||||
| "chatStoreChanged"
|
||||
| "invalidConnReq"
|
||||
| "simplexName"
|
||||
| "simplexDomain"
|
||||
| "unsupportedConnReq"
|
||||
| "connReqMessageProhibited"
|
||||
| "contactNotReady"
|
||||
@@ -1275,10 +1275,10 @@ export namespace ChatErrorType {
|
||||
type: "invalidConnReq"
|
||||
}
|
||||
|
||||
export interface SimplexName extends Interface {
|
||||
type: "simplexName"
|
||||
simplexName: SimplexNameInfo
|
||||
simplexNameError: SimplexNameError
|
||||
export interface SimplexDomain extends Interface {
|
||||
type: "simplexDomain"
|
||||
simplexDomain: SimplexDomain
|
||||
simplexDomainError: SimplexDomainError
|
||||
}
|
||||
|
||||
export interface UnsupportedConnReq extends Interface {
|
||||
@@ -2630,7 +2630,7 @@ export interface GroupInfo {
|
||||
membersRequireAttention: number // int
|
||||
viaGroupLinkUri?: string
|
||||
groupKeys?: GroupKeys
|
||||
simplexNameVerification?: boolean
|
||||
groupDomainVerified?: boolean
|
||||
}
|
||||
|
||||
export interface GroupKeys {
|
||||
@@ -3008,8 +3008,8 @@ export interface LocalProfile {
|
||||
peerType?: ChatPeerType
|
||||
localBadge?: LocalBadge
|
||||
localAlias: string
|
||||
simplexName?: SimplexNameClaim
|
||||
simplexNameVerification?: boolean
|
||||
contactDomain?: SimplexDomainClaim
|
||||
contactDomainVerified?: boolean
|
||||
}
|
||||
|
||||
export enum MemberCriteria {
|
||||
@@ -3203,12 +3203,6 @@ export enum MsgSigStatus {
|
||||
SignedNoKey = "signedNoKey",
|
||||
}
|
||||
|
||||
export interface NameClaimProof {
|
||||
linkOwnerId?: string
|
||||
presHeader: string
|
||||
signature: string
|
||||
}
|
||||
|
||||
export type NameErrorType = NameErrorType.NO_RESOLVER | NameErrorType.NOT_FOUND | NameErrorType.RESOLVER
|
||||
|
||||
export namespace NameErrorType {
|
||||
@@ -3390,7 +3384,7 @@ export interface Profile {
|
||||
preferences?: Preferences
|
||||
peerType?: ChatPeerType
|
||||
badge?: BadgeProof
|
||||
simplexName?: SimplexNameClaim
|
||||
contactDomain?: SimplexDomainClaim
|
||||
}
|
||||
|
||||
export type ProxyClientError =
|
||||
@@ -3451,7 +3445,7 @@ export namespace ProxyError {
|
||||
|
||||
export interface PublicGroupAccess {
|
||||
groupWebPage?: string
|
||||
simplexName?: SimplexNameClaim
|
||||
groupDomainClaim?: SimplexDomainClaim
|
||||
domainWebPage: boolean
|
||||
allowEmbedding: boolean
|
||||
}
|
||||
@@ -3954,29 +3948,21 @@ export interface SimplePreference {
|
||||
allow: FeatureAllowed
|
||||
}
|
||||
|
||||
export enum SimplexLinkType {
|
||||
Contact = "contact",
|
||||
Invitation = "invitation",
|
||||
Group = "group",
|
||||
Channel = "channel",
|
||||
Relay = "relay",
|
||||
}
|
||||
|
||||
export interface SimplexNameClaim {
|
||||
name: string
|
||||
proof?: NameClaimProof
|
||||
}
|
||||
|
||||
export interface SimplexNameDomain {
|
||||
export interface SimplexDomain {
|
||||
nameTLD: SimplexTLD
|
||||
domain: string
|
||||
subDomain: string[]
|
||||
}
|
||||
|
||||
export type SimplexNameError = SimplexNameError.NoValidLink | SimplexNameError.UnknownName
|
||||
export interface SimplexDomainClaim {
|
||||
domain: string
|
||||
proof?: SimplexDomainProof
|
||||
}
|
||||
|
||||
export namespace SimplexNameError {
|
||||
export type Tag = "noValidLink" | "unknownName"
|
||||
export type SimplexDomainError = SimplexDomainError.NoValidLink | SimplexDomainError.UnknownDomain
|
||||
|
||||
export namespace SimplexDomainError {
|
||||
export type Tag = "noValidLink" | "unknownDomain"
|
||||
|
||||
interface Interface {
|
||||
type: Tag
|
||||
@@ -3986,14 +3972,28 @@ export namespace SimplexNameError {
|
||||
type: "noValidLink"
|
||||
}
|
||||
|
||||
export interface UnknownName extends Interface {
|
||||
type: "unknownName"
|
||||
export interface UnknownDomain extends Interface {
|
||||
type: "unknownDomain"
|
||||
}
|
||||
}
|
||||
|
||||
export interface SimplexDomainProof {
|
||||
linkOwnerId?: string
|
||||
presHeader: string
|
||||
signature: string
|
||||
}
|
||||
|
||||
export enum SimplexLinkType {
|
||||
Contact = "contact",
|
||||
Invitation = "invitation",
|
||||
Group = "group",
|
||||
Channel = "channel",
|
||||
Relay = "relay",
|
||||
}
|
||||
|
||||
export interface SimplexNameInfo {
|
||||
nameType: SimplexNameType
|
||||
nameDomain: SimplexNameDomain
|
||||
nameDomain: SimplexDomain
|
||||
}
|
||||
|
||||
export enum SimplexNameType {
|
||||
|
||||
@@ -788,10 +788,10 @@ class ChatErrorType_chatStoreChanged(TypedDict):
|
||||
class ChatErrorType_invalidConnReq(TypedDict):
|
||||
type: Literal["invalidConnReq"]
|
||||
|
||||
class ChatErrorType_simplexName(TypedDict):
|
||||
type: Literal["simplexName"]
|
||||
simplexName: "SimplexNameInfo"
|
||||
simplexNameError: "SimplexNameError"
|
||||
class ChatErrorType_simplexDomain(TypedDict):
|
||||
type: Literal["simplexDomain"]
|
||||
simplexDomain: "SimplexDomain"
|
||||
simplexDomainError: "SimplexDomainError"
|
||||
|
||||
class ChatErrorType_unsupportedConnReq(TypedDict):
|
||||
type: Literal["unsupportedConnReq"]
|
||||
@@ -1023,7 +1023,7 @@ ChatErrorType = (
|
||||
| ChatErrorType_chatNotStopped
|
||||
| ChatErrorType_chatStoreChanged
|
||||
| ChatErrorType_invalidConnReq
|
||||
| ChatErrorType_simplexName
|
||||
| ChatErrorType_simplexDomain
|
||||
| ChatErrorType_unsupportedConnReq
|
||||
| ChatErrorType_connReqMessageProhibited
|
||||
| ChatErrorType_contactNotReady
|
||||
@@ -1080,7 +1080,7 @@ ChatErrorType = (
|
||||
| ChatErrorType_exception
|
||||
)
|
||||
|
||||
ChatErrorType_Tag = Literal["noActiveUser", "noConnectionUser", "noSndFileUser", "noRcvFileUser", "userUnknown", "userExists", "chatRelayExists", "differentActiveUser", "cantDeleteActiveUser", "cantDeleteLastUser", "cantHideLastUser", "hiddenUserAlwaysMuted", "emptyUserPassword", "userAlreadyHidden", "userNotHidden", "invalidDisplayName", "chatNotStarted", "chatNotStopped", "chatStoreChanged", "invalidConnReq", "simplexName", "unsupportedConnReq", "connReqMessageProhibited", "contactNotReady", "contactNotActive", "contactDisabled", "connectionDisabled", "groupUserRole", "groupMemberInitialRole", "contactIncognitoCantInvite", "groupIncognitoCantInvite", "groupContactRole", "groupDuplicateMember", "groupDuplicateMemberId", "groupNotJoined", "groupMemberNotActive", "cantBlockMemberForSelf", "groupMemberUserRemoved", "groupMemberNotFound", "groupCantResendInvitation", "groupInternal", "fileNotFound", "fileSize", "fileAlreadyReceiving", "fileCancelled", "fileCancel", "fileAlreadyExists", "fileWrite", "fileSend", "fileRcvChunk", "fileInternal", "fileImageType", "fileImageSize", "fileNotReceived", "fileNotApproved", "fallbackToSMPProhibited", "inlineFileProhibited", "invalidForward", "invalidChatItemUpdate", "invalidChatItemDelete", "hasCurrentCall", "noCurrentCall", "callContact", "directMessagesProhibited", "agentVersion", "agentNoSubResult", "commandError", "agentCommandError", "invalidFileDescription", "connectionIncognitoChangeProhibited", "connectionUserChangeProhibited", "peerChatVRangeIncompatible", "relayTestError", "internalError", "exception"]
|
||||
ChatErrorType_Tag = Literal["noActiveUser", "noConnectionUser", "noSndFileUser", "noRcvFileUser", "userUnknown", "userExists", "chatRelayExists", "differentActiveUser", "cantDeleteActiveUser", "cantDeleteLastUser", "cantHideLastUser", "hiddenUserAlwaysMuted", "emptyUserPassword", "userAlreadyHidden", "userNotHidden", "invalidDisplayName", "chatNotStarted", "chatNotStopped", "chatStoreChanged", "invalidConnReq", "simplexDomain", "unsupportedConnReq", "connReqMessageProhibited", "contactNotReady", "contactNotActive", "contactDisabled", "connectionDisabled", "groupUserRole", "groupMemberInitialRole", "contactIncognitoCantInvite", "groupIncognitoCantInvite", "groupContactRole", "groupDuplicateMember", "groupDuplicateMemberId", "groupNotJoined", "groupMemberNotActive", "cantBlockMemberForSelf", "groupMemberUserRemoved", "groupMemberNotFound", "groupCantResendInvitation", "groupInternal", "fileNotFound", "fileSize", "fileAlreadyReceiving", "fileCancelled", "fileCancel", "fileAlreadyExists", "fileWrite", "fileSend", "fileRcvChunk", "fileInternal", "fileImageType", "fileImageSize", "fileNotReceived", "fileNotApproved", "fallbackToSMPProhibited", "inlineFileProhibited", "invalidForward", "invalidChatItemUpdate", "invalidChatItemDelete", "hasCurrentCall", "noCurrentCall", "callContact", "directMessagesProhibited", "agentVersion", "agentNoSubResult", "commandError", "agentCommandError", "invalidFileDescription", "connectionIncognitoChangeProhibited", "connectionUserChangeProhibited", "peerChatVRangeIncompatible", "relayTestError", "internalError", "exception"]
|
||||
|
||||
ChatFeature = Literal["timedMessages", "fullDelete", "reactions", "voice", "files", "calls", "sessions"]
|
||||
|
||||
@@ -1844,7 +1844,7 @@ class GroupInfo(TypedDict):
|
||||
membersRequireAttention: int # int
|
||||
viaGroupLinkUri: NotRequired[str]
|
||||
groupKeys: NotRequired["GroupKeys"]
|
||||
simplexNameVerification: NotRequired[bool]
|
||||
groupDomainVerified: NotRequired[bool]
|
||||
|
||||
class GroupKeys(TypedDict):
|
||||
publicGroupId: str
|
||||
@@ -2107,8 +2107,8 @@ class LocalProfile(TypedDict):
|
||||
peerType: NotRequired["ChatPeerType"]
|
||||
localBadge: NotRequired["LocalBadge"]
|
||||
localAlias: str
|
||||
simplexName: NotRequired["SimplexNameClaim"]
|
||||
simplexNameVerification: NotRequired[bool]
|
||||
contactDomain: NotRequired["SimplexDomainClaim"]
|
||||
contactDomainVerified: NotRequired[bool]
|
||||
|
||||
MemberCriteria = Literal["all"]
|
||||
|
||||
@@ -2241,11 +2241,6 @@ MsgReceiptStatus = Literal["ok", "badMsgHash"]
|
||||
|
||||
MsgSigStatus = Literal["verified", "signedNoKey"]
|
||||
|
||||
class NameClaimProof(TypedDict):
|
||||
linkOwnerId: NotRequired[str]
|
||||
presHeader: str
|
||||
signature: str
|
||||
|
||||
class NameErrorType_NO_RESOLVER(TypedDict):
|
||||
type: Literal["NO_RESOLVER"]
|
||||
|
||||
@@ -2379,7 +2374,7 @@ class Profile(TypedDict):
|
||||
preferences: NotRequired["Preferences"]
|
||||
peerType: NotRequired["ChatPeerType"]
|
||||
badge: NotRequired["BadgeProof"]
|
||||
simplexName: NotRequired["SimplexNameClaim"]
|
||||
contactDomain: NotRequired["SimplexDomainClaim"]
|
||||
|
||||
class ProxyClientError_protocolError(TypedDict):
|
||||
type: Literal["protocolError"]
|
||||
@@ -2421,7 +2416,7 @@ ProxyError_Tag = Literal["PROTOCOL", "BROKER", "BASIC_AUTH", "NO_SESSION"]
|
||||
|
||||
class PublicGroupAccess(TypedDict):
|
||||
groupWebPage: NotRequired[str]
|
||||
simplexName: NotRequired["SimplexNameClaim"]
|
||||
groupDomainClaim: NotRequired["SimplexDomainClaim"]
|
||||
domainWebPage: bool
|
||||
allowEmbedding: bool
|
||||
|
||||
@@ -2764,30 +2759,35 @@ class SecurityCode(TypedDict):
|
||||
class SimplePreference(TypedDict):
|
||||
allow: "FeatureAllowed"
|
||||
|
||||
SimplexLinkType = Literal["contact", "invitation", "group", "channel", "relay"]
|
||||
|
||||
class SimplexNameClaim(TypedDict):
|
||||
name: str
|
||||
proof: NotRequired["NameClaimProof"]
|
||||
|
||||
class SimplexNameDomain(TypedDict):
|
||||
class SimplexDomain(TypedDict):
|
||||
nameTLD: "SimplexTLD"
|
||||
domain: str
|
||||
subDomain: list[str]
|
||||
|
||||
class SimplexNameError_noValidLink(TypedDict):
|
||||
class SimplexDomainClaim(TypedDict):
|
||||
domain: str
|
||||
proof: NotRequired["SimplexDomainProof"]
|
||||
|
||||
class SimplexDomainError_noValidLink(TypedDict):
|
||||
type: Literal["noValidLink"]
|
||||
|
||||
class SimplexNameError_unknownName(TypedDict):
|
||||
type: Literal["unknownName"]
|
||||
class SimplexDomainError_unknownDomain(TypedDict):
|
||||
type: Literal["unknownDomain"]
|
||||
|
||||
SimplexNameError = SimplexNameError_noValidLink | SimplexNameError_unknownName
|
||||
SimplexDomainError = SimplexDomainError_noValidLink | SimplexDomainError_unknownDomain
|
||||
|
||||
SimplexNameError_Tag = Literal["noValidLink", "unknownName"]
|
||||
SimplexDomainError_Tag = Literal["noValidLink", "unknownDomain"]
|
||||
|
||||
class SimplexDomainProof(TypedDict):
|
||||
linkOwnerId: NotRequired[str]
|
||||
presHeader: str
|
||||
signature: str
|
||||
|
||||
SimplexLinkType = Literal["contact", "invitation", "group", "channel", "relay"]
|
||||
|
||||
class SimplexNameInfo(TypedDict):
|
||||
nameType: "SimplexNameType"
|
||||
nameDomain: "SimplexNameDomain"
|
||||
nameDomain: "SimplexDomain"
|
||||
|
||||
SimplexNameType = Literal["publicGroup", "contact"]
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"https://github.com/simplex-chat/simplexmq.git"."93925b257c76ee95d9b9ea3dcf433fecdb514c9c" = "0fp1mk0bsdmy9izcccrhci2268vwqgl82maf830908kd5fiiimzs";
|
||||
"https://github.com/simplex-chat/simplexmq.git"."836254a4c6bd5e17b40acbcaf77a83802d44919e" = "1g4385sv7i1h63yk3ch2kw8hprak1dzvr34v9mn6xz0fy10g8xlg";
|
||||
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
||||
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
|
||||
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
|
||||
|
||||
@@ -66,14 +66,11 @@ import Data.Text (Text)
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
import Data.Time.Clock (NominalDiffTime, UTCTime, addUTCTime, nominalDay)
|
||||
import Simplex.FileTransfer.Description (gb, maxFileSize)
|
||||
import Simplex.Messaging.Agent.Protocol (OwnerId)
|
||||
import Simplex.Messaging.Agent.Store.DB (Binary (..), BoolInt (..), fromTextField_)
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Crypto.BBS
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON)
|
||||
import Simplex.Messaging.SimplexName (SimplexNameInfo)
|
||||
import Simplex.Messaging.Util (decodeJSON, encodeJSON)
|
||||
#if defined(dbPostgres)
|
||||
import Database.PostgreSQL.Simple.FromField (FromField (..))
|
||||
import Database.PostgreSQL.Simple.ToField (ToField (..))
|
||||
|
||||
@@ -417,7 +417,7 @@ data ChatCommand
|
||||
| APIGetCallInvitations
|
||||
| APICallStatus ContactId WebRTCCallStatus
|
||||
| APIUpdateProfile {userId :: UserId, profile :: Profile}
|
||||
| APISetUserName {userId :: UserId, simplexName :: Maybe SimplexNameInfo}
|
||||
| APISetUserDomain {userId :: UserId, simplexDomain :: Maybe SimplexDomain}
|
||||
| APISetContactPrefs {contactId :: ContactId, preferences :: Preferences}
|
||||
| APISetContactAlias {contactId :: ContactId, localAlias :: LocalAlias}
|
||||
| APISetGroupAlias {groupId :: GroupId, localAlias :: LocalAlias}
|
||||
@@ -538,8 +538,8 @@ data ChatCommand
|
||||
| APIConnectPreparedGroup {groupId :: GroupId, incognito :: IncognitoEnabled, ownerContact :: Maybe GroupOwnerContact, msgContent_ :: Maybe MsgContent}
|
||||
| APIConnect {userId :: UserId, incognito :: IncognitoEnabled, preparedLink_ :: Maybe ACreatedConnLink} -- Maybe is used to report link parsing failure as special error
|
||||
| Connect {incognito :: IncognitoEnabled, connTarget_ :: Maybe AConnectTarget}
|
||||
| APIVerifyContactName {contactId :: ContactId}
|
||||
| APIVerifyPublicGroupName {groupId :: GroupId}
|
||||
| APIVerifyContactDomain {contactId :: ContactId}
|
||||
| APIVerifyGroupDomain {groupId :: GroupId}
|
||||
| APIConnectContactViaAddress UserId IncognitoEnabled ContactId
|
||||
| ConnectSimplex IncognitoEnabled -- UserId (not used in UI)
|
||||
| DeleteContact ContactName ChatDeleteMode
|
||||
@@ -1406,9 +1406,9 @@ data ChatError
|
||||
deriving (Show, Exception)
|
||||
|
||||
-- why a resolved SimpleX name could not be used (the name itself resolved; an unregistered name is the agent's NAME NOT_FOUND)
|
||||
data SimplexNameError
|
||||
= SNENoValidLink -- the name's record has no usable contact/channel link
|
||||
| SNEUnknownName -- the resolved link's profile has no name, or a different name
|
||||
data SimplexDomainError
|
||||
= SDENoValidLink -- the name's record has no usable contact/channel link
|
||||
| SDEUnknownDomain -- the resolved link's profile has no name, or a different name
|
||||
deriving (Eq, Show)
|
||||
|
||||
data ChatErrorType
|
||||
@@ -1432,7 +1432,7 @@ data ChatErrorType
|
||||
| CEChatNotStopped
|
||||
| CEChatStoreChanged
|
||||
| CEInvalidConnReq
|
||||
| CESimplexName {simplexName :: SimplexNameInfo, simplexNameError :: SimplexNameError}
|
||||
| CESimplexDomain {simplexDomain :: SimplexDomain, simplexDomainError :: SimplexDomainError}
|
||||
| CEUnsupportedConnReq
|
||||
| CEInvalidChatMessage {connection :: Connection, msgMeta :: Maybe MsgMetaJSON, messageData :: Text, message :: String}
|
||||
| CEConnReqMessageProhibited
|
||||
@@ -1764,7 +1764,7 @@ $(JQ.deriveJSON (sumTypeJSON $ dropPrefix "GLP") ''GroupLinkPlan)
|
||||
|
||||
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "FC") ''ForwardConfirmation)
|
||||
|
||||
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "SNE") ''SimplexNameError)
|
||||
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "SDE") ''SimplexDomainError)
|
||||
|
||||
$(JQ.deriveJSON (sumTypeJSON $ dropPrefix "CE") ''ChatErrorType)
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ createActiveUser cc CoreChatOpts {chatRelay} = \case
|
||||
displayName <- T.pack <$> withPrompt "display name" getLine
|
||||
createUser loop False $ mkProfile displayName
|
||||
where
|
||||
mkProfile displayName = Profile {displayName, fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = Nothing, badge = Nothing, simplexName = Nothing}
|
||||
mkProfile displayName = Profile {displayName, fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = Nothing, badge = Nothing, contactDomain = Nothing}
|
||||
createUser onError clientService p =
|
||||
execChatCommand' (CreateActiveUser NewUser {profile = Just p, pastTimestamp = False, userChatRelay = BoolDef chatRelay, clientService = BoolDef clientService}) 0 `runReaderT` cc >>= \case
|
||||
Right (CRActiveUser user) -> pure user
|
||||
|
||||
@@ -57,7 +57,7 @@ import qualified Data.UUID as UUID
|
||||
import qualified Data.UUID.V4 as V4
|
||||
import Simplex.Chat.Library.Subscriber
|
||||
import Simplex.Chat.Badges (BadgeCredential (..), LocalBadge (..), ProofPresHeader (..), maxXFTPFileSize, mkBadgeStatus, verifyCredential)
|
||||
import Simplex.Chat.Names (NameClaimProof (..), SimplexNameClaim (..), claimName, claimProof, mkSimplexNameClaim, verifyNameProofSig)
|
||||
import Simplex.Chat.Names (SimplexDomainProof (..), SimplexDomainClaim (..), claimDomain, mkDomainClaim)
|
||||
import Simplex.Chat.Call
|
||||
import Simplex.Chat.Controller
|
||||
import Simplex.Chat.Delivery (DeliveryJobScope (..), DeliveryJobSpec (..), DeliveryWorkerScope (..))
|
||||
@@ -1493,24 +1493,24 @@ processChatCommand cxt nm = \case
|
||||
withCurrentCall contactId $ \user ct call ->
|
||||
updateCallItemStatus user ct call receivedStatus Nothing $> Just call
|
||||
APIUpdateProfile userId profile -> withUserId userId (`updateProfile` profile)
|
||||
APISetUserName userId name_ -> withUserId userId $ \user@User {profile = p@LocalProfile {contactLink, simplexName}} ->
|
||||
if (claimName <$> simplexName) == name_
|
||||
APISetUserDomain userId domain_ -> withUserId userId $ \user@User {profile = p@LocalProfile {contactLink, contactDomain}} ->
|
||||
if (claimDomain <$> contactDomain) == domain_
|
||||
then pure $ CRUserProfileNoChange user
|
||||
else do
|
||||
cl' <- case name_ of
|
||||
cl' <- case domain_ of
|
||||
Nothing -> pure contactLink
|
||||
Just ni@SimplexNameInfo {nameDomain} -> do
|
||||
UserContactLink {shortLinkDataSet, connLinkContact = CCLink fl sl_} <- withFastStore (`getUserAddress` user)
|
||||
Just domain -> do
|
||||
UserContactLink {shortLinkDataSet, connLinkContact = CCLink _ sl_} <- withFastStore (`getUserAddress` user)
|
||||
case sl_ of
|
||||
Just sl | shortLinkDataSet -> do
|
||||
NameRecord {nrSimplexContact} <- withAgent $ \a -> resolveSimplexName a nm (aUserId user) nameDomain
|
||||
unless (nameResolvesTo sl nrSimplexContact) $ throwChatError $ CESimplexName ni SNENoValidLink
|
||||
NameRecord {nrSimplexContact} <- withAgent $ \a -> resolveSimplexName a nm (aUserId user) domain
|
||||
unless (nameResolvesTo sl nrSimplexContact) $ throwChatError $ CESimplexDomain domain SDENoValidLink
|
||||
pure $ Just (CLShort sl)
|
||||
_ -> throwCmdError "create the address short link and add it to name"
|
||||
let p' = (fromLocalProfile p :: Profile) {simplexName = mkSimplexNameClaim name_ Nothing, contactLink = cl'}
|
||||
let p' = (fromLocalProfile p :: Profile) {contactDomain = mkDomainClaim <$> domain_, contactLink = cl'}
|
||||
updateProfile_ user p' True $ withFastStore $ \db -> do
|
||||
user' <- updateUserProfile db user p'
|
||||
liftIO $ setUserSimplexName db user' name_
|
||||
liftIO $ setUserSimplexDomain db user' domain_
|
||||
APISetContactPrefs contactId prefs' -> withUser $ \user -> do
|
||||
ct <- withFastStore $ \db -> getContact db cxt user contactId
|
||||
updateContactPrefs user ct prefs'
|
||||
@@ -2005,7 +2005,7 @@ processChatCommand cxt nm = \case
|
||||
subMode <- chatReadVar subscriptionMode
|
||||
-- TODO [badges] bind link and badge to handshake context
|
||||
linkProfile <- presentUserBadge user incognitoProfile $ userProfileDirect user incognitoProfile Nothing True
|
||||
let userData = contactShortLinkData linkProfile {simplexName = Nothing} Nothing
|
||||
let userData = contactShortLinkData linkProfile {contactDomain = Nothing} Nothing
|
||||
userLinkData = UserInvLinkData userData
|
||||
(connId, ccLink) <- withAgent $ \a -> createConnection a nm (aUserId user) True False SCMInvitation (Just userLinkData) Nothing IKPQOn subMode
|
||||
ccLink' <- shortenCreatedLink ccLink
|
||||
@@ -2290,20 +2290,19 @@ processChatCommand cxt nm = \case
|
||||
_ -> throwError e
|
||||
connectWithPlan user incognito ccLink plan
|
||||
Connect _ Nothing -> throwChatError CEInvalidConnReq
|
||||
APIVerifyContactName contactId -> withUser $ \user -> do
|
||||
Contact {profile = LocalProfile {simplexName}, preparedContact} <- withFastStore $ \db -> getContact db cxt user contactId
|
||||
APIVerifyContactDomain contactId -> withUser $ \user -> do
|
||||
ct@Contact {profile = LocalProfile {contactDomain}, 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 -> setContactNameVerified db user contactId v
|
||||
ct' <- withFastStore $ \db -> getContact db cxt user contactId
|
||||
domain <- maybe (throwCmdError "contact has no name to verify") pure contactDomain
|
||||
(verified, reason) <- verifyEntityDomain user nm NTContact domain connLink_
|
||||
ct' <- maybe (pure ct) (\v -> withFastStore' $ \db -> setContactDomainVerified db user ct v) verified
|
||||
pure $ CRContactNameVerified user ct' reason
|
||||
APIVerifyPublicGroupName groupId -> withUser $ \user -> do
|
||||
GroupInfo {groupProfile = GroupProfile {publicGroup}, preparedGroup} <- withFastStore $ \db -> getGroupInfo db cxt user groupId
|
||||
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 -> setGroupNameVerified db user groupId v
|
||||
g' <- withFastStore $ \db -> getGroupInfo db cxt user groupId
|
||||
APIVerifyGroupDomain groupId -> withUser $ \user -> do
|
||||
g@GroupInfo {groupProfile = GroupProfile {publicGroup}, preparedGroup} <- withFastStore $ \db -> getGroupInfo db cxt user groupId
|
||||
let connLink_ = preparedGroup >>= \PreparedGroup {connLinkToConnect = CCLink _ sLnk_} -> ACSL SCMContact <$> sLnk_
|
||||
domain <- maybe (throwCmdError "group has no name to verify") pure $ publicGroup >>= publicGroupAccess >>= groupDomainClaim
|
||||
(verified, reason) <- verifyEntityDomain user nm NTPublicGroup domain connLink_
|
||||
g' <- maybe (pure g) (\v -> withFastStore' $ \db -> setGroupDomainVerified db user g v) verified
|
||||
pure $ CRGroupNameVerified user g' reason
|
||||
APIConnectContactViaAddress userId incognito contactId -> withUserId userId $ \user -> do
|
||||
ct@Contact {profile = LocalProfile {contactLink}} <- withFastStore $ \db -> getContact db cxt user contactId
|
||||
@@ -3134,14 +3133,14 @@ processChatCommand cxt nm = \case
|
||||
updateGroupProfileByName gName $ \p -> p {description}
|
||||
ShowGroupDescription gName -> withUser $ \user ->
|
||||
CRGroupDescription user <$> withFastStore (\db -> getGroupInfoByName db cxt user gName)
|
||||
APISetPublicGroupAccess gId access@PublicGroupAccess {simplexName} -> withUser $ \user -> do
|
||||
APISetPublicGroupAccess gId access@PublicGroupAccess {groupDomainClaim = newClaim} -> withUser $ \user -> do
|
||||
gInfo@GroupInfo {groupProfile = p@GroupProfile {publicGroup}} <- withStore $ \db -> getGroupInfo db cxt user gId
|
||||
case publicGroup of
|
||||
Just pg@PublicGroupProfile {groupLink, publicGroupAccess = existingAccess} -> do
|
||||
forM_ (claimName <$> simplexName) $ \newName@SimplexNameInfo {nameDomain} ->
|
||||
when (Just newName /= (claimName <$> (existingAccess >>= publicGroupClaim))) $ do
|
||||
NameRecord {nrSimplexChannel} <- withAgent $ \a -> resolveSimplexName a nm (aUserId user) nameDomain
|
||||
unless (nameResolvesTo groupLink nrSimplexChannel) $ throwChatError $ CESimplexName newName SNENoValidLink
|
||||
forM_ (claimDomain <$> newClaim) $ \newDomain ->
|
||||
when (Just newDomain /= (claimDomain <$> (existingAccess >>= groupDomainClaim))) $ do
|
||||
NameRecord {nrSimplexChannel} <- withAgent $ \a -> resolveSimplexName a nm (aUserId user) newDomain
|
||||
unless (nameResolvesTo groupLink nrSimplexChannel) $ throwChatError $ CESimplexDomain newDomain SDENoValidLink
|
||||
runUpdateGroupProfile user gInfo p {publicGroup = Just pg {publicGroupAccess = Just access}}
|
||||
Nothing -> throwChatError $ CECommandError "not a public group"
|
||||
APICreateGroupLink groupId mRole -> withUser $ \user -> withGroupLock "createGroupLink" groupId $ do
|
||||
@@ -4209,12 +4208,13 @@ processChatCommand cxt nm = \case
|
||||
(FixedLinkData {linkConnReq = cReq, rootKey}, cData) <- getShortLinkConnReq nm user l'
|
||||
contactSLinkData_ <- mapM linkDataBadge =<< liftIO (decodeLinkUserData cData)
|
||||
let linkProfile_ = (\ContactShortLinkData {profile} -> profile) <$> contactSLinkData_
|
||||
linkName_ = linkProfile_ >>= \Profile {simplexName} -> claimName <$> simplexName
|
||||
verifiedName_ = case nl of CTName ni -> Just ni; _ -> Nothing
|
||||
refreshContact ct' = case (verifiedName_, linkProfile_) of
|
||||
linkDomain_ = linkProfile_ >>= \Profile {contactDomain} -> claimDomain <$> contactDomain
|
||||
verifiedName = case nl of CTName ni -> Just ni; _ -> Nothing
|
||||
refreshContact ct' = case (verifiedName, linkProfile_) of
|
||||
(Just _, Just p) -> updateContactFromLinkData user ct' p
|
||||
_ -> pure ct'
|
||||
forM_ verifiedName_ $ \ni -> verifyNameClaim ni linkName_
|
||||
forM_ verifiedName $ \SimplexNameInfo {nameDomain} ->
|
||||
unless (linkDomain_ == Just nameDomain) $ throwChatError $ CESimplexDomain nameDomain SDEUnknownDomain
|
||||
withFastStore' (\db -> getContactWithoutConnViaShortAddress db cxt user l') >>= \case
|
||||
Just ct' | not (contactDeleted ct') -> do
|
||||
ct'' <- refreshContact ct'
|
||||
@@ -4224,7 +4224,7 @@ processChatCommand cxt nm = \case
|
||||
ov = verifyLinkOwner rootKey owners l' sig_
|
||||
plan <- contactRequestPlan user cReq contactSLinkData_ ov
|
||||
case plan of
|
||||
CPContactAddress cap@(CAPOk {}) -> pure (con l' cReq, CPContactAddress cap {verifiedName = verifiedName_})
|
||||
CPContactAddress cap@(CAPOk {}) -> pure (con l' cReq, CPContactAddress cap {verifiedName})
|
||||
CPContactAddress (CAPKnown ct') -> do
|
||||
ct'' <- refreshContact ct'
|
||||
pure (con l' cReq, CPContactAddress (CAPKnown ct''))
|
||||
@@ -4278,18 +4278,18 @@ processChatCommand cxt nm = \case
|
||||
(Nothing, Nothing) -> pure ()
|
||||
_ -> throwChatError CEInvalidConnReq
|
||||
let ov = verifyLinkOwner rootKey owners l' sig_
|
||||
verifiedName_ = case nl of CTName ni -> Just ni; _ -> Nothing
|
||||
claimedName GroupProfile {publicGroup} = claimName <$> (publicGroup >>= publicGroupAccess >>= publicGroupClaim)
|
||||
verifiedName = case nl of CTName ni -> Just ni; _ -> Nothing
|
||||
plan <- groupJoinRequestPlan user cReq (Just linkInfo) groupSLinkData_ ov
|
||||
forM_ verifiedName_ $ \ni ->
|
||||
verifyNameClaim ni $ case plan of
|
||||
CPGroupLink (GLPOk _ (Just GroupShortLinkData {groupProfile = gp}) _ _) -> claimedName gp
|
||||
CPGroupLink (GLPKnown GroupInfo {groupProfile = gp} _ _ _) -> claimedName gp
|
||||
CPGroupLink (GLPOwnLink GroupInfo {groupProfile = gp}) -> claimedName gp
|
||||
CPGroupLink (GLPConnectingProhibit (Just GroupInfo {groupProfile = gp})) -> claimedName gp
|
||||
_ -> maybe Nothing (\GroupShortLinkData {groupProfile = gp} -> claimedName gp) groupSLinkData_
|
||||
forM_ verifiedName $ \SimplexNameInfo {nameDomain} ->
|
||||
let domain_ = (\GroupProfile {publicGroup} -> claimDomain <$> (publicGroup >>= publicGroupAccess >>= groupDomainClaim)) =<< case plan of
|
||||
CPGroupLink (GLPOk _ (Just GroupShortLinkData {groupProfile}) _ _) -> Just groupProfile
|
||||
CPGroupLink (GLPKnown GroupInfo {groupProfile} _ _ _) -> Just groupProfile
|
||||
CPGroupLink (GLPOwnLink GroupInfo {groupProfile}) -> Just groupProfile
|
||||
CPGroupLink (GLPConnectingProhibit (Just GroupInfo {groupProfile})) -> Just groupProfile
|
||||
_ -> (\GroupShortLinkData {groupProfile} -> groupProfile) <$> groupSLinkData_
|
||||
in unless (domain_ == Just nameDomain) $ throwChatError $ CESimplexDomain nameDomain SDEUnknownDomain
|
||||
pure $ case plan of
|
||||
CPGroupLink glp@(GLPOk {}) -> (con l' cReq, CPGroupLink glp {verifiedName = verifiedName_})
|
||||
CPGroupLink glp@(GLPOk {}) -> (con l' cReq, CPGroupLink glp {verifiedName})
|
||||
_ -> (con l' cReq, plan)
|
||||
where
|
||||
unsupportedGroupType = \case
|
||||
@@ -4311,13 +4311,13 @@ processChatCommand cxt nm = \case
|
||||
pure (con l' (linkConnReq fd), CPGroupLink (GLPKnown g' (BoolDef updated) ov (ListDef glOwners)))
|
||||
-- resolve a name to its first contact/channel short link
|
||||
resolveNameLink :: User -> SimplexNameInfo -> CM (ConnShortLink 'CMContact)
|
||||
resolveNameLink user ni@SimplexNameInfo {nameType, nameDomain} = do
|
||||
resolveNameLink user SimplexNameInfo {nameType, nameDomain} = do
|
||||
NameRecord {nrSimplexContact, nrSimplexChannel} <-
|
||||
withAgent $ \a -> resolveSimplexName a nm (aUserId user) nameDomain
|
||||
let (candidates, ctType) = case nameType of
|
||||
NTContact -> (nrSimplexContact, CCTContact)
|
||||
NTPublicGroup -> (nrSimplexChannel, CCTChannel)
|
||||
maybe (throwChatError $ CESimplexName ni SNENoValidLink) pure $ firstNameLink ctType candidates
|
||||
maybe (throwChatError $ CESimplexDomain nameDomain SDENoValidLink) pure $ firstNameLink ctType candidates
|
||||
connectWithPlan :: User -> IncognitoEnabled -> ACreatedConnLink -> ConnectionPlan -> CM ChatResponse
|
||||
connectWithPlan user@User {userId} incognito ccLink plan
|
||||
| connectionPlanProceed plan = do
|
||||
@@ -4789,53 +4789,31 @@ firstNameLink ctType = foldr (\t r -> nameLink t <|> r) Nothing
|
||||
nameResolvesTo :: ConnShortLink 'CMContact -> [Text] -> Bool
|
||||
nameResolvesTo sLnk = any (either (const False) (sameShortLinkContact sLnk) . strDecode . encodeUtf8)
|
||||
|
||||
verifyName :: User -> NetworkRequestMode -> SimplexNameInfo -> Maybe AConnShortLink -> Maybe NameClaimProof -> CM (Maybe Bool, Maybe Text)
|
||||
verifyName user nm claim connLink_ proof_ = case (proof_, connLink_) of
|
||||
verifyEntityDomain :: User -> NetworkRequestMode -> SimplexNameType -> SimplexDomainClaim -> Maybe AConnShortLink -> CM (Maybe Bool, Maybe Text)
|
||||
verifyEntityDomain user nm nameType SimplexDomainClaim {domain = StrJSON domain, proof = proof_} connLink_ = case (proof_, connLink_) of
|
||||
(Nothing, _) -> pure (Nothing, Just "no name proof to verify")
|
||||
(_, Nothing) -> pure (Nothing, Just "no connection link to check the name against")
|
||||
(Just proof, Just (ACSL SCMContact profileSLnk)) -> do
|
||||
let SimplexNameInfo {nameType, nameDomain} = claim
|
||||
NameRecord {nrSimplexContact, nrSimplexChannel} <-
|
||||
withAgent $ \a -> resolveSimplexName a nm (aUserId user) nameDomain
|
||||
NameRecord {nrSimplexContact, nrSimplexChannel} <- withAgent $ \a -> resolveSimplexName a nm (aUserId user) domain
|
||||
let resolvedLinks = case nameType of
|
||||
NTContact -> nrSimplexContact
|
||||
NTPublicGroup -> nrSimplexChannel
|
||||
if not (nameResolvesTo profileSLnk resolvedLinks)
|
||||
then pure (Just False, Just "the name does not resolve to this address")
|
||||
else do
|
||||
ok <- verifyProofKey nm user profileSLnk claim proof
|
||||
pure $
|
||||
if ok
|
||||
then (Just True, Nothing)
|
||||
else (Just False, Just "the name proof was not signed by this address's owner")
|
||||
ok <- verifyDomainProof proof profileSLnk
|
||||
pure (Just ok, if ok then Nothing else Just "the name proof was not signed by this address's owner")
|
||||
(Just _, Just _) -> pure (Nothing, Just "unexpected connection link type for name verification")
|
||||
|
||||
-- verify the proof signature against the profile address's owner key;
|
||||
-- getShortLinkConnReq's network/agent error propagates (UI can retry), not recorded as a verdict
|
||||
verifyProofKey :: NetworkRequestMode -> User -> ShortLinkContact -> SimplexNameInfo -> NameClaimProof -> CM Bool
|
||||
verifyProofKey nm user sLnk claim proof = do
|
||||
(FixedLinkData {rootKey}, ContactLinkData _ UserContactData {owners}) <- getShortLinkConnReq nm user sLnk
|
||||
pure $ proofSignedByOwner rootKey owners sLnk claim proof
|
||||
|
||||
proofSignedByOwner :: C.PublicKeyEd25519 -> [OwnerAuth] -> ShortLinkContact -> SimplexNameInfo -> NameClaimProof -> Bool
|
||||
proofSignedByOwner rootKey owners sLnk claim proof@NameClaimProof {linkOwnerId} =
|
||||
let key_ = case linkOwnerId of
|
||||
Nothing -> Just rootKey
|
||||
Just (StrJSON oid) -> ownerKey <$> find (\OwnerAuth {ownerId} -> ownerId == oid) owners
|
||||
in maybe False (\key -> verifyNameProofSig key claim sLnk proof) key_
|
||||
|
||||
-- connecting by name resolves the name to this address, so it is verified without checking the proof
|
||||
verifyNameClaim :: SimplexNameInfo -> Maybe SimplexNameInfo -> CM (Maybe Bool)
|
||||
verifyNameClaim ni claimedName_ = do
|
||||
unless (claimedName_ == Just ni) $ throwChatError $ CESimplexName ni SNEUnknownName
|
||||
pure (Just True)
|
||||
|
||||
verifyEntityName :: User -> NetworkRequestMode -> Maybe SimplexNameInfo -> Maybe AConnShortLink -> Maybe NameClaimProof -> String -> (Bool -> CM ()) -> CM (Maybe Text)
|
||||
verifyEntityName user nm claim_ connLink_ proof_ noNameErr persist = do
|
||||
claim <- maybe (throwCmdError noNameErr) pure claim_
|
||||
(verdict, reason) <- verifyName user nm claim connLink_ proof_
|
||||
forM_ verdict persist
|
||||
pure reason
|
||||
where
|
||||
verifyDomainProof :: SimplexDomainProof -> ShortLinkContact -> CM Bool
|
||||
verifyDomainProof SimplexDomainProof {linkOwnerId, presHeader, signature} sLnk@(CSLContact _ ct srv key) = do
|
||||
(FixedLinkData {rootKey}, ContactLinkData _ UserContactData {owners}) <- getShortLinkConnReq nm user sLnk
|
||||
let ownerKey_ = case linkOwnerId of
|
||||
Nothing -> Just rootKey
|
||||
Just (StrJSON oid) -> ownerKey <$> find (\OwnerAuth {ownerId} -> ownerId == oid) owners
|
||||
pure $ maybe False (\k -> C.verify' k signature proofPayload) ownerKey_
|
||||
where
|
||||
proofPayload = strEncode (Str "simplex_domain_v1", presHeader, domain, ct, srv, key)
|
||||
|
||||
data ConnectViaContactResult
|
||||
= CVRConnectedContact Contact
|
||||
@@ -5313,7 +5291,7 @@ chatCommandP =
|
||||
"/_call status @" *> (APICallStatus <$> A.decimal <* A.space <*> strP),
|
||||
"/_call get" $> APIGetCallInvitations,
|
||||
"/_profile " *> (APIUpdateProfile <$> A.decimal <* A.space <*> jsonP),
|
||||
"/_set_name " *> (APISetUserName <$> A.decimal <*> optional (A.space *> strP)),
|
||||
"/_set domain " *> (APISetUserDomain <$> A.decimal <*> optional (A.space *> strP)),
|
||||
"/_set alias @" *> (APISetContactAlias <$> A.decimal <*> (A.space *> textP <|> pure "")),
|
||||
"/_set alias #" *> (APISetGroupAlias <$> A.decimal <*> (A.space *> textP <|> pure "")),
|
||||
"/_set alias :" *> (APISetConnectionAlias <$> A.decimal <*> (A.space *> textP <|> pure "")),
|
||||
@@ -5484,8 +5462,8 @@ chatCommandP =
|
||||
"/_set conn user :" *> (APIChangeConnectionUser <$> A.decimal <* A.space <*> A.decimal),
|
||||
("/connect" <|> "/c") *> (AddContact <$> incognitoP),
|
||||
("/connect" <|> "/c") *> (Connect <$> incognitoP <* A.space <*> ((Just <$> strP) <|> A.takeTill isSpace $> Nothing)),
|
||||
"/_verify name @" *> (APIVerifyContactName <$> A.decimal),
|
||||
"/_verify name #" *> (APIVerifyPublicGroupName <$> A.decimal),
|
||||
"/_verify domain @" *> (APIVerifyContactDomain <$> A.decimal),
|
||||
"/_verify domain #" *> (APIVerifyGroupDomain <$> A.decimal),
|
||||
ForwardMessage <$> chatNameP <* " <- @" <*> displayNameP <* A.space <*> msgTextP,
|
||||
ForwardGroupMessage <$> chatNameP <* " <- #" <*> displayNameP <* A.space <* A.char '@' <*> (Just <$> displayNameP) <* A.space <*> msgTextP,
|
||||
ForwardGroupMessage <$> chatNameP <* " <- #" <*> displayNameP <*> pure Nothing <* A.space <*> msgTextP,
|
||||
@@ -5661,10 +5639,10 @@ chatCommandP =
|
||||
onOffP = ("on" $> True) <|> ("off" $> False)
|
||||
publicGroupAccessP = do
|
||||
groupWebPage <- optional (" web=" *> (safeDecodeUtf8 <$> A.takeTill A.isSpace))
|
||||
simplexName <- optional (" name=" *> strP)
|
||||
domainWebPage <- (" name_page=" *> onOffP) <|> pure False
|
||||
groupDomain <- optional (" domain=" *> strP)
|
||||
domainWebPage <- (" domain_page=" *> onOffP) <|> pure False
|
||||
allowEmbedding <- (" embed=" *> onOffP) <|> pure False
|
||||
pure PublicGroupAccess {groupWebPage, simplexName = mkSimplexNameClaim simplexName Nothing, domainWebPage, allowEmbedding}
|
||||
pure PublicGroupAccess {groupWebPage, groupDomainClaim = mkDomainClaim <$> groupDomain, domainWebPage, allowEmbedding}
|
||||
profileNameDescr = (,) <$> displayNameP <*> shortDescrP
|
||||
-- 'Help with bot':'link <ID>','Menu of commands':[...]
|
||||
botCommandsP :: Parser [ChatBotCommand]
|
||||
@@ -5685,7 +5663,7 @@ chatCommandP =
|
||||
newUserP relay = do
|
||||
(cName, shortDescr) <- profileNameDescr
|
||||
service <- (" service=" *> onOffP) <|> pure False
|
||||
let profile = Just Profile {displayName = cName, fullName = "", shortDescr, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = Nothing, badge = Nothing, simplexName = Nothing}
|
||||
let profile = Just Profile {displayName = cName, fullName = "", shortDescr, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = Nothing, badge = Nothing, contactDomain = Nothing}
|
||||
pure NewUser {profile, pastTimestamp = False, userChatRelay = BoolDef relay, clientService = BoolDef service}
|
||||
newBotUserP = do
|
||||
files_ <- optional $ "files=" *> onOffP <* A.space
|
||||
@@ -5694,7 +5672,7 @@ chatCommandP =
|
||||
let preferences = case files_ of
|
||||
Just True -> Nothing
|
||||
_ -> Just (emptyChatPrefs :: Preferences) {files = Just FilesPreference {allow = FANo}}
|
||||
profile = Just Profile {displayName = cName, fullName = "", shortDescr, image = Nothing, contactLink = Nothing, peerType = Just CPTBot, preferences, badge = Nothing, simplexName = Nothing}
|
||||
profile = Just Profile {displayName = cName, fullName = "", shortDescr, image = Nothing, contactLink = Nothing, peerType = Just CPTBot, preferences, badge = Nothing, contactDomain = Nothing}
|
||||
pure NewUser {profile, pastTimestamp = False, userChatRelay = BoolDef False, clientService = BoolDef service}
|
||||
jsonP :: J.FromJSON a => Parser a
|
||||
jsonP = J.eitherDecodeStrict' <$?> A.takeByteString
|
||||
|
||||
@@ -54,7 +54,7 @@ import Data.Time (addUTCTime)
|
||||
import Data.Time.Calendar (fromGregorian)
|
||||
import Data.Time.Clock (UTCTime (..), diffUTCTime, getCurrentTime, nominalDiffTimeToSeconds, secondsToDiffTime)
|
||||
import Simplex.Chat.Badges (BadgeCredential (..), ProofPresHeader (..), BadgeProof (..), BadgeStatus (..), LocalBadge (..), badgeProof, mkBadgeStatus, verifyBadge)
|
||||
import Simplex.Chat.Names (claimName, mkSimplexNameClaim)
|
||||
import Simplex.Chat.Names (SimplexDomainClaim (..), claimDomain)
|
||||
import Simplex.Chat.Call
|
||||
import Simplex.Chat.Controller
|
||||
import Simplex.Chat.Files
|
||||
@@ -1244,11 +1244,11 @@ memberInfo g m@GroupMember {memberId, memberRole, memberProfile, memberPubKey, a
|
||||
}
|
||||
|
||||
redactedMemberProfile :: GroupInfo -> GroupMember -> Profile -> Profile
|
||||
redactedMemberProfile g m Profile {displayName, fullName, shortDescr, image, contactLink = lnk, peerType, badge, simplexName} =
|
||||
Profile {displayName, fullName, shortDescr = removeSimplexLink =<< shortDescr, image, contactLink, preferences = Nothing, peerType, badge, simplexName = redactedName}
|
||||
redactedMemberProfile g m Profile {displayName, fullName, shortDescr, image, contactLink = lnk, peerType, badge, contactDomain} =
|
||||
Profile {displayName, fullName, shortDescr = removeSimplexLink =<< shortDescr, image, contactLink, preferences = Nothing, peerType, badge, contactDomain = redactedDomain}
|
||||
where
|
||||
contactLink = if allowSimplexLinks then lnk else Nothing
|
||||
redactedName = mkSimplexNameClaim (if allowDirect then claimName <$> simplexName else Nothing) 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
|
||||
@@ -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, simplexNameVerification}} linkProfile@Profile {simplexName = newClaim}
|
||||
updateContactFromLinkData user ct@Contact {profile = profile@LocalProfile {contactDomain = prevClaim, contactDomainVerified}} linkProfile@Profile {contactDomain = newClaim}
|
||||
| profileChanged || verifyChanged = do
|
||||
cxt <- chatStoreCxt
|
||||
when profileChanged $ void $ withStore $ \db -> updateContactProfile db cxt user ct linkProfile
|
||||
when verifyChanged $ withStore' $ \db -> setContactNameVerified db user contactId True
|
||||
withStore $ \db -> getContact db cxt user contactId
|
||||
withFastStore $ \db -> do
|
||||
ct' <- updateContactProfile db cxt user ct linkProfile
|
||||
if verifyChanged then liftIO $ setContactDomainVerified db user ct' True else pure ct'
|
||||
| otherwise = pure ct
|
||||
where
|
||||
profileChanged = fromLocalProfile profile /= linkProfile
|
||||
claimChanged = (claimName <$> prevClaim) /= (claimName <$> newClaim)
|
||||
verifyChanged = simplexNameVerification /= Just True || claimChanged
|
||||
claimChanged = (claimDomain <$> prevClaim) /= (claimDomain <$> newClaim)
|
||||
verifyChanged = contactDomainVerified /= Just True || claimChanged
|
||||
|
||||
-- TODO [relays] owner: set owners on updating link data (multi-owner)
|
||||
groupLinkData :: GroupInfo -> GroupLink -> [GroupRelay] -> (UserConnLinkData 'CMContact, CRClientData)
|
||||
@@ -3109,7 +3109,7 @@ simplexTeamContactProfile =
|
||||
peerType = Nothing,
|
||||
preferences = Nothing,
|
||||
badge = Nothing,
|
||||
simplexName = Nothing
|
||||
contactDomain = Nothing
|
||||
}
|
||||
|
||||
simplexStatusContactProfile :: Profile
|
||||
@@ -3123,7 +3123,7 @@ simplexStatusContactProfile =
|
||||
peerType = Just CPTBot,
|
||||
preferences = Nothing,
|
||||
badge = Nothing,
|
||||
simplexName = Nothing
|
||||
contactDomain = Nothing
|
||||
}
|
||||
|
||||
timeItToView :: String -> CM' a -> CM' a
|
||||
|
||||
@@ -1422,7 +1422,7 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
|
||||
void $ sendGroupMessages user gInfo Nothing False recipients events
|
||||
where
|
||||
updateRelay :: DB.Connection -> GroupRelay -> ([GroupRelay], Bool, [ShortLinkContact]) -> IO ([GroupRelay], Bool, [ShortLinkContact])
|
||||
updateRelay db relay@GroupRelay {groupMemberId, relayLink, relayStatus} (acc, changed, newlyActiveLinks) =
|
||||
updateRelay db relay@GroupRelay {relayLink, relayStatus} (acc, changed, newlyActiveLinks) =
|
||||
case relayLink of
|
||||
Just rLink
|
||||
-- version is gated upstream at publish (getPublishableGroupRelays): an RSAccepted relay
|
||||
@@ -3335,7 +3335,7 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
|
||||
-- transfer record + its scratch file in one transaction (file owned by the transfer, keyed per source)
|
||||
rft@RcvFileTransfer {fileId} <- withStore $ \db -> do
|
||||
transferId <- liftIO $ createRosterTransfer db gInfo (groupMemberId' fromMember) newVer fileDigest (groupMemberId' author) brokerTs relayHdr
|
||||
createRosterRcvFile db userId gInfo fromMember transferId sharedMsgId rosterFInv (Just IFMSent) (fromIntegral chSize)
|
||||
createRosterRcvFile db userId gInfo fromMember transferId sharedMsgId rosterFInv (Just IFMSent) chSize
|
||||
-- accept the chat-item-free file before chunk 1 (FIFO before it) so chunk 1 isn't rejected on RFSNew
|
||||
-- transient scratch file (consumed into roster_blob, then deleted): temp folder, not the user's files folder / Downloads
|
||||
tmpDir <- lift getChatTempDirectory
|
||||
@@ -3361,10 +3361,10 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
|
||||
Just RcvRosterTransfer {rosterTransferId = transferId, rosterTransferVersion = pendingVer, rosterTransferDigest = pendingDigest, rosterTransferOwnerGMId = ownerGMId, rosterTransferBrokerTs = rosterBrokerTs, rosterTransferHeader = header_} -> do
|
||||
owner_ <- withStore' $ \db -> eitherToMaybe <$> runExceptT (getGroupMemberById db cxt user ownerGMId)
|
||||
blob <- readAssembledRoster
|
||||
let isRelay = isUserGrpFwdRelay gInfo
|
||||
let isRelay' = isUserGrpFwdRelay gInfo
|
||||
ackErr err = do
|
||||
cleanupRosterTransferById transferId
|
||||
when isRelay $ forM_ owner_ $ \owner -> sendRosterAck gInfo owner pendingVer (Just err)
|
||||
when isRelay' $ forM_ owner_ $ \owner -> sendRosterAck gInfo owner pendingVer (Just err)
|
||||
if FD.FileDigest (LC.sha512Hash (LB.fromStrict blob)) /= pendingDigest
|
||||
then ackErr "relay could not verify the roster blob"
|
||||
else case parseAll rosterBlobP blob of
|
||||
@@ -3388,7 +3388,7 @@ processAgentMessageConn cxt user@User {userId} corrId agentConnId agentMessage =
|
||||
forM_ results_ $ \results -> do
|
||||
emitRosterResults gInfo author rosterBrokerTs results
|
||||
-- ack while setting up (own status accepted/acknowledged); a serving (active) relay must not ack broadcasts.
|
||||
when (isRelay && (relayOwnStatus gInfo == Just RSAccepted || relayOwnStatus gInfo == Just RSAcknowledgedRoster)) $ do
|
||||
when (isRelay' && (relayOwnStatus gInfo == Just RSAccepted || relayOwnStatus gInfo == Just RSAcknowledgedRoster)) $ do
|
||||
sendRosterAck gInfo author pendingVer Nothing
|
||||
withStore' $ \db -> void $ updateRelayOwnStatusFromTo db gInfo RSAccepted RSAcknowledgedRoster
|
||||
where
|
||||
|
||||
+19
-40
@@ -2,31 +2,27 @@
|
||||
{-# LANGUAGE DataKinds #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
{-# LANGUAGE FlexibleInstances #-}
|
||||
{-# LANGUAGE GADTs #-}
|
||||
{-# LANGUAGE KindSignatures #-}
|
||||
{-# LANGUAGE NamedFieldPuns #-}
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
|
||||
module Simplex.Chat.Names
|
||||
( SimplexNameClaim (..),
|
||||
mkSimplexNameClaim,
|
||||
claimName,
|
||||
claimProof,
|
||||
setClaimProof,
|
||||
NameClaimProof (..),
|
||||
verifyNameProofSig,
|
||||
( SimplexDomainClaim (..),
|
||||
SimplexDomainProof (..),
|
||||
mkDomainClaim,
|
||||
claimDomain,
|
||||
)
|
||||
where
|
||||
|
||||
import qualified Data.Aeson.TH as JQ
|
||||
import Data.ByteString.Char8 (ByteString)
|
||||
import Simplex.Chat.Badges (ProofPresHeader)
|
||||
import Simplex.Messaging.Agent.Protocol (ConnShortLink (..), ConnectionMode (..), OwnerId)
|
||||
import Simplex.Messaging.Agent.Protocol (OwnerId, SimplexDomain)
|
||||
import Simplex.Messaging.Agent.Store.DB (fromTextField_)
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Parsers (defaultJSON)
|
||||
import Simplex.Messaging.SimplexName (SimplexNameInfo)
|
||||
import Simplex.Messaging.Util (decodeJSON, encodeJSON)
|
||||
#if defined(dbPostgres)
|
||||
import Database.PostgreSQL.Simple.FromField (FromField (..))
|
||||
@@ -36,47 +32,30 @@ import Database.SQLite.Simple.FromField (FromField (..))
|
||||
import Database.SQLite.Simple.ToField (ToField (..))
|
||||
#endif
|
||||
|
||||
-- A name claim proof: signed by the address owner's key (linkOwnerId = Just oid when a channel
|
||||
-- owner other than the address signs, Nothing when the address's own root key signs) over
|
||||
-- the name-proof payload, binding the name to the address (see nameProofPayload).
|
||||
data NameClaimProof = NameClaimProof
|
||||
-- A name claim proof: signed by the address owner's key over proof payload - see verifyDomainProof.
|
||||
data SimplexDomainProof = SimplexDomainProof
|
||||
{ linkOwnerId :: Maybe (StrJSON "OwnerId" OwnerId),
|
||||
presHeader :: ProofPresHeader,
|
||||
signature :: C.Signature 'C.Ed25519
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
nameProofPayload :: SimplexNameInfo -> ProofPresHeader -> ConnShortLink 'CMContact -> ByteString
|
||||
nameProofPayload name presHeader (CSLContact _ ct srv key) =
|
||||
strEncode (Str "simplex_names_v1", presHeader, name, ct, srv, key)
|
||||
$(JQ.deriveJSON defaultJSON ''SimplexDomainProof)
|
||||
|
||||
verifyNameProofSig :: C.PublicKeyEd25519 -> SimplexNameInfo -> ConnShortLink 'CMContact -> NameClaimProof -> Bool
|
||||
verifyNameProofSig ownerKey name sLnk NameClaimProof {presHeader, signature} =
|
||||
C.verify' ownerKey signature (nameProofPayload name presHeader sLnk)
|
||||
instance ToField SimplexDomainProof where toField = toField . encodeJSON
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''NameClaimProof)
|
||||
instance FromField SimplexDomainProof where fromField = fromTextField_ decodeJSON
|
||||
|
||||
-- stored as JSON in contact_profiles.simplex_name_proof
|
||||
instance ToField NameClaimProof where toField = toField . encodeJSON
|
||||
|
||||
instance FromField NameClaimProof where fromField = fromTextField_ decodeJSON
|
||||
|
||||
data SimplexNameClaim = SimplexNameClaim
|
||||
{ name :: StrJSON "SimplexNameInfo" SimplexNameInfo,
|
||||
proof :: Maybe NameClaimProof
|
||||
data SimplexDomainClaim = SimplexDomainClaim
|
||||
{ domain :: StrJSON "SimplexDomain" SimplexDomain,
|
||||
proof :: Maybe SimplexDomainProof
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
mkSimplexNameClaim :: Maybe SimplexNameInfo -> Maybe NameClaimProof -> Maybe SimplexNameClaim
|
||||
mkSimplexNameClaim name_ proof_ = (\n -> SimplexNameClaim (StrJSON n) proof_) <$> name_
|
||||
mkDomainClaim :: SimplexDomain -> SimplexDomainClaim
|
||||
mkDomainClaim = (`SimplexDomainClaim` Nothing) . StrJSON
|
||||
|
||||
claimName :: SimplexNameClaim -> SimplexNameInfo
|
||||
claimName (SimplexNameClaim n _) = unStrJSON n
|
||||
claimDomain :: SimplexDomainClaim -> SimplexDomain
|
||||
claimDomain (SimplexDomainClaim n _) = unStrJSON n
|
||||
|
||||
claimProof :: SimplexNameClaim -> Maybe NameClaimProof
|
||||
claimProof (SimplexNameClaim _ p) = p
|
||||
|
||||
setClaimProof :: Maybe NameClaimProof -> SimplexNameClaim -> SimplexNameClaim
|
||||
setClaimProof p (SimplexNameClaim n _) = SimplexNameClaim n p
|
||||
|
||||
$(JQ.deriveJSON defaultJSON ''SimplexNameClaim)
|
||||
$(JQ.deriveJSON defaultJSON ''SimplexDomainClaim)
|
||||
|
||||
@@ -10,7 +10,7 @@ generateRandomProfile :: IO Profile
|
||||
generateRandomProfile = do
|
||||
adjective <- pick adjectives
|
||||
noun <- pickNoun adjective 2
|
||||
pure $ Profile {displayName = adjective <> noun, fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = Nothing, badge = Nothing, simplexName = Nothing}
|
||||
pure $ Profile {displayName = adjective <> noun, fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = Nothing, badge = Nothing, contactDomain = Nothing}
|
||||
where
|
||||
pick :: [a] -> IO a
|
||||
pick xs = (xs !!) <$> randomRIO (0, length xs - 1)
|
||||
|
||||
@@ -35,7 +35,6 @@ import Simplex.Chat.Protocol
|
||||
import Simplex.Chat.Store.Direct
|
||||
import Simplex.Chat.Store.Groups
|
||||
import Simplex.Chat.Store.Shared
|
||||
import Simplex.Chat.Names (mkSimplexNameClaim)
|
||||
import Simplex.Chat.Types
|
||||
import Simplex.Messaging.Agent.Protocol (ConnId)
|
||||
import Simplex.Messaging.Agent.Store.AgentStore (firstRow, firstRow', fromOnlyBI, maybeFirstRow)
|
||||
@@ -118,15 +117,15 @@ getConnectionEntity db cxt user@User {userId, userContactId} agentConnId = do
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx,
|
||||
p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
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
|
||||
|]
|
||||
(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 :. (cpsimplexName, cpContactNameVerification, cpsimplexNameProof)) =
|
||||
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim cpsimplexName cpsimplexNameProof, simplexNameVerification = unBI <$> cpContactNameVerification, 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 :. domainRow) =
|
||||
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, contactDomain = rowToContactDomain domainRow, contactDomainVerified = rowToDomainVerified domainRow, 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
|
||||
@@ -145,27 +144,26 @@ getConnectionEntity db cxt user@User {userId, userContactId} agentConnId = do
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof,
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.use_relays, g.relay_own_status,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri, g.group_domain_verified,
|
||||
g.root_priv_key, g.root_pub_key, g.member_priv_key,
|
||||
g.simplex_name_verification,
|
||||
-- GroupInfo {membership}
|
||||
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,
|
||||
-- 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_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.simplex_name, pu.simplex_name_verification, pu.simplex_name_proof,
|
||||
pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, pu.badge_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.contact_domain, pu.contact_domain_proof, pu.contact_domain_verified,
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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
|
||||
|
||||
@@ -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_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx, cp.simplex_name, cp.simplex_name_verification, cp.simplex_name_proof,
|
||||
cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx, cp.contact_domain, cp.contact_domain_proof, cp.contact_domain_verified,
|
||||
-- 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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
FROM contact_requests cr
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
WHERE cr.user_id = ?
|
||||
|
||||
@@ -51,7 +51,7 @@ module Simplex.Chat.Store.Direct
|
||||
getContactViaShortLinkToConnect,
|
||||
getContactIdByName,
|
||||
updateContactProfile,
|
||||
setContactNameVerified,
|
||||
setContactDomainVerified,
|
||||
updateContactUserPreferences,
|
||||
updateContactAlias,
|
||||
updateContactConnectionAlias,
|
||||
@@ -111,11 +111,11 @@ import Data.Type.Equality
|
||||
import Simplex.Chat.Badges (badgeToRow)
|
||||
import Simplex.Chat.Messages
|
||||
import Simplex.Chat.Store.Shared
|
||||
import Simplex.Chat.Names (claimName, claimProof, setClaimProof)
|
||||
import Simplex.Chat.Names (SimplexDomainClaim (..))
|
||||
import Simplex.Chat.Types
|
||||
import Simplex.Chat.Types.Preferences
|
||||
import Simplex.Chat.Types.UITheme
|
||||
import Simplex.Messaging.Agent.Protocol (AConnectionRequestUri (..), ACreatedConnLink (..), ConnId, ConnShortLink, ConnectionModeI (..), ConnectionRequestUri, CreatedConnLink (..), SConnectionMode (..), UserId)
|
||||
import Simplex.Messaging.Agent.Protocol (AConnectionRequestUri (..), ACreatedConnLink (..), ConnId, ConnShortLink, ConnectionModeI (..), ConnectionRequestUri, CreatedConnLink (..), SConnectionMode (..), SimplexNameInfo (..), UserId)
|
||||
import Simplex.Messaging.Agent.Store.AgentStore (firstRow, maybeFirstRow)
|
||||
import Simplex.Messaging.Agent.Store.DB (BoolInt (..))
|
||||
import qualified Simplex.Messaging.Agent.Store.DB as DB
|
||||
@@ -326,7 +326,7 @@ getContactByConnReqHash db cxt user@User {userId} cReqHash1 cReqHash2 = do
|
||||
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_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx,
|
||||
cp.simplex_name, cp.simplex_name_verification, cp.simplex_name_proof,
|
||||
cp.contact_domain, cp.contact_domain_proof, cp.contact_domain_verified,
|
||||
-- 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,
|
||||
@@ -404,13 +404,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 nameVerified = do
|
||||
createPreparedContact db cxt user p connLinkToConnect welcomeSharedMsgId verified_ = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
let prepared = Just (connLinkToConnect, welcomeSharedMsgId)
|
||||
ctUserPreferences = newContactUserPrefs user p
|
||||
contactId <- createContact_ db cxt user p ctUserPreferences prepared "" currentTs
|
||||
liftIO $ mapM_ (setContactNameVerified db user contactId) nameVerified
|
||||
getContact db cxt user contactId
|
||||
ct <- getContact db cxt user =<< createContact_ db cxt user p ctUserPreferences prepared "" currentTs
|
||||
liftIO $ maybe (pure ct) (setContactDomainVerified db user ct) verified_
|
||||
|
||||
updatePreparedContactUser :: DB.Connection -> StoreCxt -> User -> Contact -> User -> ExceptT StoreError IO Contact
|
||||
updatePreparedContactUser
|
||||
@@ -570,14 +569,14 @@ 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, simplexNameVerification = prevVerification}, userPreferences} = c
|
||||
Profile {displayName = newName, simplexName, preferences} = p'
|
||||
Contact {contactId, localDisplayName, profile = lp@LocalProfile {profileId, displayName, localAlias, contactDomain = prevClaim, contactDomainVerified = prevVerification}, userPreferences} = c
|
||||
Profile {displayName = newName, contactDomain, preferences} = p'
|
||||
mergedPreferences = contactUserPreferences user userPreferences preferences $ contactConnIncognito c
|
||||
claimChanged = (claimName <$> prevClaim) /= (claimName <$> simplexName)
|
||||
p'' = (p' :: Profile) {simplexName = setClaimProof (if claimChanged then Nothing else claimProof =<< prevClaim) <$> simplexName}
|
||||
claimChanged = (domain <$> prevClaim) /= (domain <$> contactDomain)
|
||||
p'' = (p' :: Profile) {contactDomain = (\d -> d {proof = if claimChanged then Nothing else proof =<< prevClaim}) <$> contactDomain}
|
||||
clearVerificationIfClaimChanged =
|
||||
when claimChanged $
|
||||
DB.execute db "UPDATE contact_profiles SET simplex_name_verification = NULL WHERE user_id = ? AND contact_profile_id = ?" (userId, profileId)
|
||||
DB.execute db "UPDATE contact_profiles SET contact_domain_verified = NULL WHERE user_id = ? AND contact_profile_id = ?" (userId, profileId)
|
||||
updateContactProfile' currentTs badgeVerified profile
|
||||
| displayName == newName = do
|
||||
liftIO $ updateContactProfile_' db userId profileId p'' badgeVerified currentTs
|
||||
@@ -590,15 +589,16 @@ updateContactProfile db cxt user@User {userId} c p' = do
|
||||
clearVerificationIfClaimChanged
|
||||
pure $ Right c {localDisplayName = ldn, profile, mergedPreferences}
|
||||
|
||||
setContactNameVerified :: DB.Connection -> User -> ContactId -> Bool -> IO ()
|
||||
setContactNameVerified db User {userId} contactId verified =
|
||||
setContactDomainVerified :: DB.Connection -> User -> Contact -> Bool -> IO Contact
|
||||
setContactDomainVerified db User {userId} ct@Contact {contactId, profile = p} verified = do
|
||||
DB.execute
|
||||
db
|
||||
[sql|
|
||||
UPDATE contact_profiles SET simplex_name_verification = ?
|
||||
UPDATE contact_profiles SET contact_domain_verified = ?
|
||||
WHERE contact_profile_id IN (SELECT contact_profile_id FROM contacts WHERE user_id = ? AND contact_id = ?)
|
||||
|]
|
||||
(BI verified, userId, contactId)
|
||||
pure (ct {profile = p {contactDomainVerified = Just verified}} :: Contact)
|
||||
|
||||
updateContactUserPreferences :: DB.Connection -> User -> Contact -> Preferences -> IO Contact
|
||||
updateContactUserPreferences db user@User {userId} c@Contact {contactId} userPreferences = do
|
||||
@@ -731,18 +731,17 @@ updateContactProfile_ db userId profileId profile badgeVerified = do
|
||||
updateContactProfile_' db userId profileId profile badgeVerified currentTs
|
||||
|
||||
updateContactProfile_' :: DB.Connection -> UserId -> ProfileId -> Profile -> Maybe Bool -> UTCTime -> IO ()
|
||||
updateContactProfile_' db userId profileId Profile {displayName, fullName, shortDescr, image, contactLink, simplexName, preferences, peerType, badge} badgeVerified updatedAt =
|
||||
updateContactProfile_' db userId profileId Profile {displayName, fullName, shortDescr, image, contactLink, contactDomain, preferences, peerType, badge} badgeVerified updatedAt =
|
||||
DB.execute
|
||||
db
|
||||
[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_extra = ?, badge_master_key = ?, badge_signature = ?, badge_key_idx = ?,
|
||||
simplex_name = ?,
|
||||
simplex_name_proof = ?
|
||||
contact_domain = ?, contact_domain_proof = ?
|
||||
WHERE user_id = ? AND contact_profile_id = ?
|
||||
|]
|
||||
((displayName, fullName, shortDescr, image, contactLink, preferences, peerType, updatedAt) :. badgeToRow badge badgeVerified :. (claimName <$> simplexName, claimProof =<< simplexName) :. (userId, profileId))
|
||||
((displayName, fullName, shortDescr, image, contactLink, preferences, peerType, updatedAt) :. badgeToRow badge badgeVerified :. contactDomainToRow contactDomain :. (userId, profileId))
|
||||
|
||||
-- update only member profile fields (when member doesn't have associated contact - we can reset contactLink and prefs)
|
||||
updateMemberContactProfileReset_ :: DB.Connection -> UserId -> ProfileId -> Profile -> Maybe Bool -> IO ()
|
||||
@@ -751,18 +750,17 @@ updateMemberContactProfileReset_ db userId profileId profile badgeVerified = do
|
||||
updateMemberContactProfileReset_' db userId profileId profile badgeVerified currentTs
|
||||
|
||||
updateMemberContactProfileReset_' :: DB.Connection -> UserId -> ProfileId -> Profile -> Maybe Bool -> UTCTime -> IO ()
|
||||
updateMemberContactProfileReset_' db userId profileId Profile {displayName, fullName, shortDescr, image, simplexName, badge} badgeVerified updatedAt =
|
||||
updateMemberContactProfileReset_' db userId profileId Profile {displayName, fullName, shortDescr, image, contactDomain, badge} badgeVerified updatedAt =
|
||||
DB.execute
|
||||
db
|
||||
[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_extra = ?, badge_master_key = ?, badge_signature = ?, badge_key_idx = ?,
|
||||
simplex_name = ?,
|
||||
simplex_name_proof = ?
|
||||
contact_domain = ?, contact_domain_proof = ?
|
||||
WHERE user_id = ? AND contact_profile_id = ?
|
||||
|]
|
||||
((displayName, fullName, shortDescr, image, updatedAt) :. badgeToRow badge badgeVerified :. (claimName <$> simplexName, claimProof =<< simplexName) :. (userId, profileId))
|
||||
((displayName, fullName, shortDescr, image, updatedAt) :. badgeToRow badge badgeVerified :. contactDomainToRow contactDomain :. (userId, profileId))
|
||||
|
||||
-- update only member profile fields (when member has associated contact - we keep contactLink and prefs)
|
||||
updateMemberContactProfile_ :: DB.Connection -> UserId -> ProfileId -> Profile -> Maybe Bool -> IO ()
|
||||
@@ -771,18 +769,17 @@ updateMemberContactProfile_ db userId profileId profile badgeVerified = do
|
||||
updateMemberContactProfile_' db userId profileId profile badgeVerified currentTs
|
||||
|
||||
updateMemberContactProfile_' :: DB.Connection -> UserId -> ProfileId -> Profile -> Maybe Bool -> UTCTime -> IO ()
|
||||
updateMemberContactProfile_' db userId profileId Profile {displayName, fullName, shortDescr, image, simplexName, badge} badgeVerified updatedAt =
|
||||
updateMemberContactProfile_' db userId profileId Profile {displayName, fullName, shortDescr, image, contactDomain, badge} badgeVerified updatedAt =
|
||||
DB.execute
|
||||
db
|
||||
[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_extra = ?, badge_master_key = ?, badge_signature = ?, badge_key_idx = ?,
|
||||
simplex_name = ?,
|
||||
simplex_name_proof = ?
|
||||
contact_domain = ?, contact_domain_proof = ?
|
||||
WHERE user_id = ? AND contact_profile_id = ?
|
||||
|]
|
||||
((displayName, fullName, shortDescr, image, updatedAt) :. badgeToRow badge badgeVerified :. (claimName <$> simplexName, claimProof =<< simplexName) :. (userId, profileId))
|
||||
((displayName, fullName, shortDescr, image, updatedAt) :. badgeToRow badge badgeVerified :. contactDomainToRow contactDomain :. (userId, profileId))
|
||||
|
||||
updateContactLDN_ :: DB.Connection -> User -> Int64 -> ContactName -> ContactName -> UTCTime -> IO ()
|
||||
updateContactLDN_ db user@User {userId} contactId displayName newName updatedAt = do
|
||||
@@ -805,7 +802,7 @@ getContactToConnect :: DB.Connection -> StoreCxt -> User -> ContactNameOrLink ->
|
||||
getContactToConnect db cxt user@User {userId} = \case
|
||||
CTLink sl -> first (`CCLink` Just sl) <$$> getContactViaShortLinkToConnect db cxt user sl
|
||||
CTName ni ->
|
||||
liftIO (maybeFirstRow id $ DB.query db byNameQuery (userId, ni)) >>= \case
|
||||
liftIO (maybeFirstRow id $ DB.query db byNameQuery (userId, nameDomain ni)) >>= \case
|
||||
Just (ctId :: Int64, Just (ACR cMode cReq), Just (sLnk :: ShortLinkContact)) | Just Refl <- testEquality cMode SCMContact ->
|
||||
Just . (CCLink cReq (Just sLnk),) <$> getContact db cxt user ctId
|
||||
_ -> pure Nothing
|
||||
@@ -814,7 +811,7 @@ getContactToConnect db cxt user@User {userId} = \case
|
||||
[sql|
|
||||
SELECT ct.contact_id, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect FROM contacts ct
|
||||
JOIN contact_profiles cp ON cp.contact_profile_id = ct.contact_profile_id
|
||||
WHERE ct.user_id = ? AND cp.simplex_name = ? AND cp.simplex_name_verification = 1 AND ct.deleted = 0
|
||||
WHERE ct.user_id = ? AND cp.contact_domain = ? AND cp.contact_domain_verified = 1 AND ct.deleted = 0
|
||||
|]
|
||||
|
||||
getUserContacts :: DB.Connection -> StoreCxt -> User -> IO [Contact]
|
||||
@@ -857,7 +854,7 @@ contactRequestQuery =
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx,
|
||||
p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
FROM contact_requests cr
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
|]
|
||||
@@ -978,7 +975,7 @@ getContact_ db cxt user@User {userId} contactId deleted = do
|
||||
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_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx,
|
||||
cp.simplex_name, cp.simplex_name_verification, cp.simplex_name_proof,
|
||||
cp.contact_domain, cp.contact_domain_proof, cp.contact_domain_verified,
|
||||
-- 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,
|
||||
|
||||
@@ -46,7 +46,7 @@ module Simplex.Chat.Store.Groups
|
||||
getGroupViaShortLinkToConnect,
|
||||
getGroupInfoByGroupLinkHash,
|
||||
updateGroupProfile,
|
||||
setGroupNameVerified,
|
||||
setGroupDomainVerified,
|
||||
updateGroupPreferences,
|
||||
updateGroupProfileFromMember,
|
||||
getGroupIdByName,
|
||||
@@ -222,7 +222,7 @@ import qualified Data.Text as T
|
||||
import Data.Time.Clock (NominalDiffTime, UTCTime (..), addUTCTime, getCurrentTime)
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
import Simplex.Chat.Badges (BadgeRow, badgeToRow, verifyBadge_)
|
||||
import Simplex.Chat.Names (NameClaimProof, claimName)
|
||||
import Simplex.Chat.Names (SimplexDomainClaim (..))
|
||||
import Simplex.Chat.Messages
|
||||
import Simplex.Chat.Operators
|
||||
import Simplex.Chat.Protocol hiding (Binary)
|
||||
@@ -233,7 +233,7 @@ import Simplex.Chat.Types.MemberRelations (IntroductionDirection (..), MemberRel
|
||||
import Simplex.Chat.Types.Preferences
|
||||
import Simplex.Chat.Types.Shared
|
||||
import Simplex.Chat.Types.UITheme
|
||||
import Simplex.Messaging.Agent.Protocol (ConfirmationId, ConnId, CreatedConnLink (..), InvitationId, OwnerAuth (..), SimplexNameInfo, UserId)
|
||||
import Simplex.Messaging.Agent.Protocol (ConfirmationId, ConnId, CreatedConnLink (..), InvitationId, OwnerAuth (..), SimplexNameInfo (..), UserId)
|
||||
import Simplex.Messaging.Agent.Store.AgentStore (firstRow, fromOnlyBI, maybeFirstRow)
|
||||
import qualified Simplex.FileTransfer.Description as FD
|
||||
import Simplex.Messaging.Encoding (smpDecode, smpEncode)
|
||||
@@ -254,11 +254,11 @@ import Database.SQLite.Simple (Only (..), Query, (:.) (..))
|
||||
import Database.SQLite.Simple.QQ (sql)
|
||||
#endif
|
||||
|
||||
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)
|
||||
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 :. ContactDomainRow) :. (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 :. (profilesimplexName, profileContactNameVerification, profilesimplexNameProof)) :. (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 :. (profilesimplexName, profileContactNameVerification, profilesimplexNameProof)) :. (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 :. domainRow) :. (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 :. domainRow) :. (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
|
||||
@@ -398,7 +398,7 @@ createNewGroup db cxt user@User {userId} groupProfile incognitoProfile useRelays
|
||||
INSERT INTO group_profiles
|
||||
(display_name, full_name, short_descr, description, image,
|
||||
group_type, group_link, public_group_id,
|
||||
group_web_page, simplex_name, domain_web_page, allow_embedding, simplex_name_proof,
|
||||
group_web_page, group_domain, domain_web_page, allow_embedding, group_domain_proof,
|
||||
user_id, preferences, member_admission, created_at, updated_at)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|]
|
||||
@@ -447,7 +447,7 @@ createNewGroup db cxt user@User {userId} groupProfile incognitoProfile useRelays
|
||||
membersRequireAttention = 0,
|
||||
viaGroupLinkUri = Nothing,
|
||||
groupKeys,
|
||||
simplexNameVerification = Nothing
|
||||
groupDomainVerified = Nothing
|
||||
}
|
||||
|
||||
-- | creates a new group record for the group the current user was invited to, or returns an existing one
|
||||
@@ -526,7 +526,7 @@ createGroupInvitation db cxt user@User {userId} contact@Contact {contactId, acti
|
||||
membersRequireAttention = 0,
|
||||
viaGroupLinkUri = Nothing,
|
||||
groupKeys = Nothing,
|
||||
simplexNameVerification = Nothing
|
||||
groupDomainVerified = Nothing
|
||||
},
|
||||
groupMemberId
|
||||
)
|
||||
@@ -643,7 +643,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_ nameVerified = do
|
||||
createPreparedGroup db gVar cxt user@User {userId, userContactId} groupProfile business connLinkToConnect welcomeSharedMsgId useRelays userMemberRole publicMemberCount_ verified_ = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
let prepared = Just (connLinkToConnect, welcomeSharedMsgId)
|
||||
(groupId, groupLDN) <- createGroup_ db userId groupProfile prepared Nothing useRelays Nothing publicMemberCount_ currentTs
|
||||
@@ -661,9 +661,9 @@ 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_ (setGroupNameVerified db user groupId) nameVerified
|
||||
g <- getGroupInfo db cxt user groupId
|
||||
pure (g, hostMember_)
|
||||
g' <- liftIO $ maybe (pure g) (setGroupDomainVerified db user g) verified_
|
||||
pure (g', hostMember_)
|
||||
where
|
||||
insertHost_ currentTs groupId groupLDN = do
|
||||
randHostId <- liftIO $ encodedRandomBytes gVar 12
|
||||
@@ -905,7 +905,7 @@ createGroup_ db userId groupProfile prepared business useRelays relayOwnStatus p
|
||||
INSERT INTO group_profiles
|
||||
(display_name, full_name, short_descr, description, image,
|
||||
group_type, group_link, public_group_id,
|
||||
group_web_page, simplex_name, domain_web_page, allow_embedding, simplex_name_proof,
|
||||
group_web_page, group_domain, domain_web_page, allow_embedding, group_domain_proof,
|
||||
user_id, preferences, member_admission, created_at, updated_at)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|]
|
||||
@@ -1078,7 +1078,7 @@ getGroupToConnect :: DB.Connection -> StoreCxt -> User -> ContactNameOrLink -> E
|
||||
getGroupToConnect db cxt user@User {userId} = \case
|
||||
CTLink sl -> first (`CCLink` Just sl) <$$> getGroupViaShortLinkToConnect db cxt user sl
|
||||
CTName ni ->
|
||||
liftIO (maybeFirstRow id $ DB.query db byNameQuery (userId, ni)) >>= \case
|
||||
liftIO (maybeFirstRow id $ DB.query db byNameQuery (userId, nameDomain ni)) >>= \case
|
||||
Just (gId :: Int64, Just cReq, Just (sLnk :: ShortLinkContact)) -> Just . (CCLink cReq (Just sLnk),) <$> getGroupInfo db cxt user gId
|
||||
_ -> pure Nothing
|
||||
where
|
||||
@@ -1086,7 +1086,7 @@ getGroupToConnect db cxt user@User {userId} = \case
|
||||
[sql|
|
||||
SELECT g.group_id, g.conn_full_link_to_connect, g.conn_short_link_to_connect FROM groups g
|
||||
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
|
||||
WHERE g.user_id = ? AND gp.simplex_name = ? AND g.simplex_name_verification = 1
|
||||
WHERE g.user_id = ? AND gp.group_domain = ? AND g.group_domain_verified = 1
|
||||
|]
|
||||
|
||||
getGroupMember :: DB.Connection -> StoreCxt -> User -> GroupId -> GroupMemberId -> ExceptT StoreError IO GroupMember
|
||||
@@ -1950,7 +1950,7 @@ getRelayPublishableGroups db User {userId, userContactId} =
|
||||
db
|
||||
[sql|
|
||||
SELECT g.group_id, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof
|
||||
FROM groups g
|
||||
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
|
||||
JOIN group_members mu ON mu.group_id = g.group_id AND mu.contact_id = ?
|
||||
@@ -2655,12 +2655,12 @@ updateGroupProfile db user@User {userId} g@GroupInfo {groupId, localDisplayName,
|
||||
pure $ Right $ (g' :: GroupInfo) {localDisplayName = ldn, groupProfile = p', fullGroupPreferences}
|
||||
where
|
||||
fullGroupPreferences = mergeGroupPreferences groupPreferences
|
||||
groupClaim pg = claimName <$> (pg >>= publicGroupAccess >>= publicGroupClaim)
|
||||
groupClaim pg = domain <$> (pg >>= publicGroupAccess >>= groupDomainClaim)
|
||||
claimChanged = groupClaim oldPublicGroup /= groupClaim publicGroup
|
||||
g' = if claimChanged then (g :: GroupInfo) {simplexNameVerification = Nothing} else g
|
||||
g' = if claimChanged then (g :: GroupInfo) {groupDomainVerified = Nothing} else g
|
||||
clearVerificationIfClaimChanged =
|
||||
when claimChanged $
|
||||
DB.execute db "UPDATE groups SET simplex_name_verification = NULL WHERE user_id = ? AND group_id = ?" (userId, groupId)
|
||||
DB.execute db "UPDATE groups SET group_domain_verified = NULL WHERE user_id = ? AND group_id = ?" (userId, groupId)
|
||||
(groupType_, groupLink_) = case publicGroup of
|
||||
Just PublicGroupProfile {groupType, groupLink} -> (Just groupType, Just groupLink)
|
||||
Nothing -> (Nothing, Nothing)
|
||||
@@ -2671,7 +2671,7 @@ updateGroupProfile db user@User {userId} g@GroupInfo {groupId, localDisplayName,
|
||||
UPDATE group_profiles
|
||||
SET display_name = ?, full_name = ?, short_descr = ?, description = ?, image = ?,
|
||||
group_type = ?, group_link = ?,
|
||||
group_web_page = ?, simplex_name = ?, domain_web_page = ?, allow_embedding = ?, simplex_name_proof = ?,
|
||||
group_web_page = ?, group_domain = ?, domain_web_page = ?, allow_embedding = ?, group_domain_proof = ?,
|
||||
preferences = ?, member_admission = ?, updated_at = ?
|
||||
WHERE group_profile_id IN (
|
||||
SELECT group_profile_id
|
||||
@@ -2687,12 +2687,13 @@ updateGroupProfile db user@User {userId} g@GroupInfo {groupId, localDisplayName,
|
||||
(ldn, currentTs, userId, groupId)
|
||||
safeDeleteLDN db user localDisplayName
|
||||
|
||||
setGroupNameVerified :: DB.Connection -> User -> GroupId -> Bool -> IO ()
|
||||
setGroupNameVerified db User {userId} groupId verified =
|
||||
setGroupDomainVerified :: DB.Connection -> User -> GroupInfo -> Bool -> IO GroupInfo
|
||||
setGroupDomainVerified db User {userId} g@GroupInfo {groupId} verified = do
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE groups SET simplex_name_verification = ? WHERE user_id = ? AND group_id = ?"
|
||||
"UPDATE groups SET group_domain_verified = ? WHERE user_id = ? AND group_id = ?"
|
||||
(BI verified, userId, groupId)
|
||||
pure g {groupDomainVerified = Just verified}
|
||||
|
||||
updateGroupPreferences :: DB.Connection -> User -> GroupInfo -> GroupPreferences -> IO GroupInfo
|
||||
updateGroupPreferences db User {userId} g@GroupInfo {groupId, groupProfile = p} ps = do
|
||||
@@ -2726,7 +2727,7 @@ updateGroupProfileFromMember db user g@GroupInfo {groupId} Profile {displayName
|
||||
[sql|
|
||||
SELECT gp.display_name, gp.full_name, gp.short_descr, gp.description, gp.image,
|
||||
gp.group_type, gp.group_link, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof,
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof,
|
||||
gp.preferences, gp.member_admission
|
||||
FROM group_profiles gp
|
||||
JOIN groups g ON gp.group_profile_id = g.group_profile_id
|
||||
@@ -2776,9 +2777,9 @@ getGroupInfoViaUserTarget db cxt user@User {userId} target = fmap eitherToMaybe
|
||||
FROM user_contact_links ucl
|
||||
JOIN groups g ON g.group_id = ucl.group_id
|
||||
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
|
||||
WHERE ucl.user_id = ? AND gp.simplex_name = ?
|
||||
WHERE ucl.user_id = ? AND gp.group_domain = ?
|
||||
|]
|
||||
(userId, ni)
|
||||
(userId, nameDomain ni)
|
||||
toConnReqGroupId = \case
|
||||
-- cReq is "not null", group_id is nullable
|
||||
(cReq, Just (sLnk :: ShortLinkContact), Just groupId) -> Right (cReq, sLnk, groupId)
|
||||
@@ -3330,7 +3331,6 @@ setMemberContactStartedConnection db Contact {contactId} = do
|
||||
"UPDATE contacts SET grp_direct_inv_started_connection = ?, updated_at = ? WHERE contact_id = ?"
|
||||
(BI True, currentTs, contactId)
|
||||
|
||||
-- | Updates the member profile (the profile writer persists simplex_name).
|
||||
updateMemberProfile :: DB.Connection -> StoreCxt -> User -> GroupMember -> Profile -> ExceptT StoreError IO GroupMember
|
||||
updateMemberProfile db cxt user@User {userId} m p' = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
@@ -3354,7 +3354,6 @@ updateMemberProfile db cxt user@User {userId} m p' = do
|
||||
safeDeleteLDN db user localDisplayName
|
||||
pure $ Right m {localDisplayName = ldn, memberProfile}
|
||||
|
||||
-- | Updates the member's contact profile (the profile writer persists simplex_name).
|
||||
updateContactMemberProfile :: DB.Connection -> StoreCxt -> User -> GroupMember -> Contact -> Profile -> ExceptT StoreError IO (GroupMember, Contact)
|
||||
updateContactMemberProfile db cxt user@User {userId} m ct@Contact {contactId} p' = do
|
||||
currentTs <- liftIO getCurrentTime
|
||||
|
||||
@@ -715,7 +715,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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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
|
||||
@@ -1139,7 +1139,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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
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
|
||||
@@ -3070,7 +3070,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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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
|
||||
@@ -3079,14 +3079,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_extra, rp.badge_master_key, rp.badge_signature, rp.badge_key_idx, rp.simplex_name, rp.simplex_name_verification, rp.simplex_name_proof,
|
||||
rp.badge_proof, rp.badge_pres_header, rp.badge_expiry, rp.badge_type, rp.badge_verified, rp.badge_extra, rp.badge_master_key, rp.badge_signature, rp.badge_key_idx, rp.contact_domain, rp.contact_domain_proof, rp.contact_domain_verified,
|
||||
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_extra, dbp.badge_master_key, dbp.badge_signature, dbp.badge_key_idx, dbp.simplex_name, dbp.simplex_name_verification, dbp.simplex_name_proof,
|
||||
dbp.badge_proof, dbp.badge_pres_header, dbp.badge_expiry, dbp.badge_type, dbp.badge_verified, dbp.badge_extra, dbp.badge_master_key, dbp.badge_signature, dbp.badge_key_idx, dbp.contact_domain, dbp.contact_domain_proof, dbp.contact_domain_verified,
|
||||
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
|
||||
|
||||
@@ -9,13 +9,13 @@ import Text.RawString.QQ (r)
|
||||
m20260603_simplex_name :: Text
|
||||
m20260603_simplex_name =
|
||||
[r|
|
||||
ALTER TABLE contact_profiles ADD COLUMN simplex_name TEXT;
|
||||
ALTER TABLE contact_profiles ADD COLUMN simplex_name_verification SMALLINT;
|
||||
ALTER TABLE contact_profiles ADD COLUMN simplex_name_proof TEXT;
|
||||
ALTER TABLE groups ADD COLUMN simplex_name_verification SMALLINT;
|
||||
ALTER TABLE group_profiles ADD COLUMN simplex_name TEXT;
|
||||
ALTER TABLE group_profiles DROP COLUMN group_domain;
|
||||
ALTER TABLE group_profiles ADD COLUMN simplex_name_proof TEXT;
|
||||
ALTER TABLE contact_profiles ADD COLUMN contact_domain TEXT;
|
||||
ALTER TABLE contact_profiles ADD COLUMN contact_domain_proof TEXT;
|
||||
ALTER TABLE contact_profiles ADD COLUMN contact_domain_verified SMALLINT;
|
||||
|
||||
ALTER TABLE group_profiles ADD COLUMN group_domain_proof TEXT;
|
||||
ALTER TABLE groups ADD COLUMN group_domain_verified SMALLINT;
|
||||
|
||||
ALTER TABLE user_contact_links ADD COLUMN link_priv_sig_key BYTEA;
|
||||
|
||||
ALTER TABLE server_operators ADD COLUMN smp_role_names SMALLINT NOT NULL DEFAULT 0;
|
||||
@@ -25,14 +25,14 @@ UPDATE server_operators SET smp_role_names = 1 WHERE server_operator_tag = 'simp
|
||||
down_m20260603_simplex_name :: Text
|
||||
down_m20260603_simplex_name =
|
||||
[r|
|
||||
ALTER TABLE server_operators DROP COLUMN smp_role_names;
|
||||
ALTER TABLE contact_profiles DROP COLUMN contact_domain;
|
||||
ALTER TABLE contact_profiles DROP COLUMN contact_domain_proof;
|
||||
ALTER TABLE contact_profiles DROP COLUMN contact_domain_verified;
|
||||
|
||||
ALTER TABLE group_profiles DROP COLUMN group_domain_proof;
|
||||
ALTER TABLE groups DROP COLUMN group_domain_verified;
|
||||
|
||||
ALTER TABLE user_contact_links DROP COLUMN link_priv_sig_key;
|
||||
ALTER TABLE group_profiles DROP COLUMN simplex_name_proof;
|
||||
ALTER TABLE group_profiles ADD COLUMN group_domain TEXT;
|
||||
ALTER TABLE group_profiles DROP COLUMN simplex_name;
|
||||
ALTER TABLE groups DROP COLUMN simplex_name_verification;
|
||||
ALTER TABLE contact_profiles DROP COLUMN simplex_name_proof;
|
||||
ALTER TABLE contact_profiles DROP COLUMN simplex_name_verification;
|
||||
ALTER TABLE contact_profiles DROP COLUMN simplex_name;
|
||||
|
||||
ALTER TABLE server_operators DROP COLUMN smp_role_names;
|
||||
|]
|
||||
|
||||
@@ -541,9 +541,9 @@ CREATE TABLE test_chat_schema.contact_profiles (
|
||||
badge_master_key bytea,
|
||||
badge_signature bytea,
|
||||
badge_key_idx bigint,
|
||||
simplex_name text,
|
||||
simplex_name_verification smallint,
|
||||
simplex_name_proof text
|
||||
contact_domain text,
|
||||
contact_domain_proof text,
|
||||
contact_domain_verified smallint
|
||||
);
|
||||
|
||||
|
||||
@@ -867,10 +867,10 @@ CREATE TABLE test_chat_schema.group_profiles (
|
||||
group_link bytea,
|
||||
public_group_id bytea,
|
||||
group_web_page text,
|
||||
group_domain text,
|
||||
domain_web_page bigint,
|
||||
allow_embedding bigint,
|
||||
simplex_name text,
|
||||
simplex_name_proof text
|
||||
group_domain_proof text
|
||||
);
|
||||
|
||||
|
||||
@@ -994,7 +994,7 @@ CREATE TABLE test_chat_schema.groups (
|
||||
roster_sending_owner_gm_id bigint,
|
||||
roster_broker_ts timestamp with time zone,
|
||||
roster_blob bytea,
|
||||
simplex_name_verification smallint
|
||||
group_domain_verified smallint
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ module Simplex.Chat.Store.Profiles
|
||||
getUserAddressConnection,
|
||||
deleteUserAddress,
|
||||
getUserAddress,
|
||||
setUserSimplexName,
|
||||
setUserSimplexDomain,
|
||||
getUserContactLinkById,
|
||||
getGroupLinkInfo,
|
||||
getUserContactLinkByConnReq,
|
||||
@@ -106,13 +106,13 @@ import Simplex.Chat.Operators
|
||||
import Simplex.Chat.Protocol
|
||||
import Simplex.Chat.Store.Direct
|
||||
import Simplex.Chat.Store.Shared
|
||||
import Simplex.Chat.Names (claimName, mkSimplexNameClaim)
|
||||
import Simplex.Chat.Names (claimDomain, mkDomainClaim)
|
||||
import Simplex.Chat.Types
|
||||
import Simplex.Chat.Types.Preferences
|
||||
import Simplex.Chat.Types.Shared
|
||||
import Simplex.Chat.Types.UITheme
|
||||
import Simplex.Messaging.Agent.Env.SQLite (ServerRoles (..))
|
||||
import Simplex.Messaging.Agent.Protocol (ACorrId, ConnId, ConnectionLink (..), CreatedConnLink (..), SimplexNameInfo, UserId)
|
||||
import Simplex.Messaging.Agent.Protocol (ACorrId, ConnId, ConnectionLink (..), CreatedConnLink (..), SimplexDomain, SimplexNameInfo (..), UserId)
|
||||
import Simplex.Messaging.Agent.Store.AgentStore (firstRow, maybeFirstRow)
|
||||
import Simplex.Messaging.Agent.Store.DB (BoolInt (..))
|
||||
import qualified Simplex.Messaging.Agent.Store.DB as DB
|
||||
@@ -386,14 +386,14 @@ setUserBadge db user@User {userId, profile = p@LocalProfile {profileId}} localBa
|
||||
DB.execute db "UPDATE users SET user_member_profile_updated_at = ? WHERE user_id = ?" (ts, userId)
|
||||
pure (user :: User) {profile = p {localBadge}, userMemberProfileUpdatedAt = Just ts}
|
||||
|
||||
setUserSimplexName :: DB.Connection -> User -> Maybe SimplexNameInfo -> IO User
|
||||
setUserSimplexName db user@User {userId, profile = p@LocalProfile {profileId}} name_ = do
|
||||
setUserSimplexDomain :: DB.Connection -> User -> Maybe SimplexDomain -> IO User
|
||||
setUserSimplexDomain db user@User {userId, profile = p@LocalProfile {profileId}} domain_ = do
|
||||
ts <- getCurrentTime
|
||||
DB.execute
|
||||
db
|
||||
"UPDATE contact_profiles SET simplex_name = ?, updated_at = ? WHERE user_id = ? AND contact_profile_id = ?"
|
||||
(name_, ts, userId, profileId)
|
||||
pure (user :: User) {profile = p {simplexName = mkSimplexNameClaim name_ Nothing}}
|
||||
"UPDATE contact_profiles SET contact_domain = ?, updated_at = ? WHERE user_id = ? AND contact_profile_id = ?"
|
||||
(domain_, ts, userId, profileId)
|
||||
pure (user :: User) {profile = p {contactDomain = mkDomainClaim <$> domain_}}
|
||||
|
||||
setUserProfileContactLink :: DB.Connection -> User -> Maybe UserContactLink -> IO User
|
||||
setUserProfileContactLink db user@User {userId, profile = p@LocalProfile {profileId}} ucl_ = do
|
||||
@@ -417,14 +417,14 @@ getUserContactProfiles db User {userId} =
|
||||
<$> DB.query
|
||||
db
|
||||
[sql|
|
||||
SELECT display_name, full_name, short_descr, image, contact_link, chat_peer_type, simplex_name, preferences
|
||||
SELECT display_name, full_name, short_descr, image, contact_link, chat_peer_type, contact_domain, preferences
|
||||
FROM contact_profiles
|
||||
WHERE user_id = ?
|
||||
|]
|
||||
(Only userId)
|
||||
where
|
||||
toContactProfile :: (ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, Maybe SimplexNameInfo, Maybe Preferences) -> Profile
|
||||
toContactProfile (displayName, fullName, shortDescr, image, contactLink, peerType, simplexName, preferences) = Profile {displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim simplexName Nothing, peerType, preferences, badge = Nothing}
|
||||
toContactProfile :: (ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, Maybe SimplexDomain, Maybe Preferences) -> Profile
|
||||
toContactProfile (displayName, fullName, shortDescr, image, contactLink, peerType, domain_, preferences) = Profile {displayName, fullName, shortDescr, image, contactLink, contactDomain = mkDomainClaim <$> domain_, peerType, preferences, badge = Nothing}
|
||||
|
||||
createUserContactLink :: DB.Connection -> User -> ConnId -> CreatedLinkContact -> SubscriptionMode -> C.PrivateKeyEd25519 -> ExceptT StoreError IO ()
|
||||
createUserContactLink db User {userId} agentConnId (CCLink cReq shortLink) subMode linkPrivSigKey =
|
||||
@@ -558,12 +558,12 @@ getUserContactLinkByConnReq db User {userId} (cReqSchema1, cReqSchema2) =
|
||||
DB.query db (userContactLinkQuery <> " WHERE user_id = ? AND conn_req_contact IN (?,?)") (userId, cReqSchema1, cReqSchema2)
|
||||
|
||||
getUserContactLinkViaTarget :: DB.Connection -> User -> ContactNameOrLink -> IO (Maybe UserContactLink)
|
||||
getUserContactLinkViaTarget db User {userId, profile = LocalProfile {simplexName}} = \case
|
||||
getUserContactLinkViaTarget db User {userId, profile = LocalProfile {contactDomain}} = \case
|
||||
CTLink shortLink ->
|
||||
maybeFirstRow toUserContactLink $
|
||||
DB.query db (userContactLinkQuery <> " WHERE user_id = ? AND short_link_contact = ?") (userId, shortLink)
|
||||
CTName ni
|
||||
| (claimName <$> simplexName) == Just ni ->
|
||||
| (claimDomain <$> contactDomain) == Just (nameDomain ni) ->
|
||||
maybeFirstRow toUserContactLink $
|
||||
DB.query db (userContactLinkQuery <> " WHERE user_id = ? AND group_id IS NULL AND short_link_contact IS NOT NULL") (Only userId)
|
||||
| otherwise -> pure Nothing
|
||||
|
||||
@@ -8,13 +8,13 @@ import Database.SQLite.Simple.QQ (sql)
|
||||
m20260603_simplex_name :: Query
|
||||
m20260603_simplex_name =
|
||||
[sql|
|
||||
ALTER TABLE contact_profiles ADD COLUMN simplex_name TEXT;
|
||||
ALTER TABLE contact_profiles ADD COLUMN simplex_name_verification INTEGER;
|
||||
ALTER TABLE contact_profiles ADD COLUMN simplex_name_proof TEXT;
|
||||
ALTER TABLE groups ADD COLUMN simplex_name_verification INTEGER;
|
||||
ALTER TABLE group_profiles ADD COLUMN simplex_name TEXT;
|
||||
ALTER TABLE group_profiles DROP COLUMN group_domain;
|
||||
ALTER TABLE group_profiles ADD COLUMN simplex_name_proof TEXT;
|
||||
ALTER TABLE contact_profiles ADD COLUMN contact_domain TEXT;
|
||||
ALTER TABLE contact_profiles ADD COLUMN contact_domain_proof TEXT;
|
||||
ALTER TABLE contact_profiles ADD COLUMN contact_domain_verified INTEGER;
|
||||
|
||||
ALTER TABLE group_profiles ADD COLUMN group_domain_proof TEXT;
|
||||
ALTER TABLE groups ADD COLUMN group_domain_verified INTEGER;
|
||||
|
||||
ALTER TABLE user_contact_links ADD COLUMN link_priv_sig_key BLOB;
|
||||
|
||||
ALTER TABLE server_operators ADD COLUMN smp_role_names INTEGER NOT NULL DEFAULT 0;
|
||||
@@ -24,14 +24,14 @@ UPDATE server_operators SET smp_role_names = 1 WHERE server_operator_tag = 'simp
|
||||
down_m20260603_simplex_name :: Query
|
||||
down_m20260603_simplex_name =
|
||||
[sql|
|
||||
ALTER TABLE server_operators DROP COLUMN smp_role_names;
|
||||
ALTER TABLE contact_profiles DROP COLUMN contact_domain;
|
||||
ALTER TABLE contact_profiles DROP COLUMN contact_domain_proof;
|
||||
ALTER TABLE contact_profiles DROP COLUMN contact_domain_verified;
|
||||
|
||||
ALTER TABLE group_profiles DROP COLUMN group_domain_proof;
|
||||
ALTER TABLE groups DROP COLUMN group_domain_verified;
|
||||
|
||||
ALTER TABLE user_contact_links DROP COLUMN link_priv_sig_key;
|
||||
ALTER TABLE group_profiles DROP COLUMN simplex_name_proof;
|
||||
ALTER TABLE group_profiles ADD COLUMN group_domain TEXT;
|
||||
ALTER TABLE group_profiles DROP COLUMN simplex_name;
|
||||
ALTER TABLE groups DROP COLUMN simplex_name_verification;
|
||||
ALTER TABLE contact_profiles DROP COLUMN simplex_name_proof;
|
||||
ALTER TABLE contact_profiles DROP COLUMN simplex_name_verification;
|
||||
ALTER TABLE contact_profiles DROP COLUMN simplex_name;
|
||||
|
||||
ALTER TABLE server_operators DROP COLUMN smp_role_names;
|
||||
|]
|
||||
|
||||
@@ -125,7 +125,7 @@ Query:
|
||||
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_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx, cp.simplex_name, cp.simplex_name_verification, cp.simplex_name_proof,
|
||||
cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx, cp.contact_domain, cp.contact_domain_proof, cp.contact_domain_verified,
|
||||
-- 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,
|
||||
@@ -144,27 +144,26 @@ Query:
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof,
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.use_relays, g.relay_own_status,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri, g.group_domain_verified,
|
||||
g.root_priv_key, g.root_pub_key, g.member_priv_key,
|
||||
g.simplex_name_verification,
|
||||
-- GroupInfo {membership}
|
||||
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,
|
||||
-- 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_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.simplex_name, pu.simplex_name_verification, pu.simplex_name_proof,
|
||||
pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, pu.badge_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.contact_domain, pu.contact_domain_proof, pu.contact_domain_verified,
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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
|
||||
@@ -402,7 +401,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
FROM contact_requests cr
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
WHERE cr.user_id = ?
|
||||
@@ -465,7 +464,7 @@ Query:
|
||||
FROM user_contact_links ucl
|
||||
JOIN groups g ON g.group_id = ucl.group_id
|
||||
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
|
||||
WHERE ucl.user_id = ? AND gp.simplex_name = ?
|
||||
WHERE ucl.user_id = ? AND gp.group_domain = ?
|
||||
|
||||
Plan:
|
||||
SEARCH ucl USING INDEX sqlite_autoindex_user_contact_links_1 (user_id=?)
|
||||
@@ -709,7 +708,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx,
|
||||
p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
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
|
||||
@@ -1008,7 +1007,7 @@ SEARCH delivery_tasks USING COVERING INDEX idx_delivery_tasks_next (group_id=? A
|
||||
Query:
|
||||
SELECT gp.display_name, gp.full_name, gp.short_descr, gp.description, gp.image,
|
||||
gp.group_type, gp.group_link, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof,
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof,
|
||||
gp.preferences, gp.member_admission
|
||||
FROM group_profiles gp
|
||||
JOIN groups g ON gp.group_profile_id = g.group_profile_id
|
||||
@@ -1052,7 +1051,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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
|
||||
@@ -1283,7 +1282,7 @@ Query:
|
||||
INSERT INTO group_profiles
|
||||
(display_name, full_name, short_descr, description, image,
|
||||
group_type, group_link, public_group_id,
|
||||
group_web_page, simplex_name, domain_web_page, allow_embedding, simplex_name_proof,
|
||||
group_web_page, group_domain, domain_web_page, allow_embedding, group_domain_proof,
|
||||
user_id, preferences, member_admission, created_at, updated_at)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
|
||||
@@ -1361,7 +1360,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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
|
||||
@@ -1370,14 +1369,14 @@ Query:
|
||||
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_extra, rp.badge_master_key, rp.badge_signature, rp.badge_key_idx, rp.simplex_name, rp.simplex_name_verification, rp.simplex_name_proof,
|
||||
rp.badge_proof, rp.badge_pres_header, rp.badge_expiry, rp.badge_type, rp.badge_verified, rp.badge_extra, rp.badge_master_key, rp.badge_signature, rp.badge_key_idx, rp.contact_domain, rp.contact_domain_proof, rp.contact_domain_verified,
|
||||
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_extra, dbp.badge_master_key, dbp.badge_signature, dbp.badge_key_idx, dbp.simplex_name, dbp.simplex_name_verification, dbp.simplex_name_proof,
|
||||
dbp.badge_proof, dbp.badge_pres_header, dbp.badge_expiry, dbp.badge_type, dbp.badge_verified, dbp.badge_extra, dbp.badge_master_key, dbp.badge_signature, dbp.badge_key_idx, dbp.contact_domain, dbp.contact_domain_proof, dbp.contact_domain_verified,
|
||||
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
|
||||
@@ -1431,7 +1430,7 @@ Query:
|
||||
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_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx,
|
||||
cp.simplex_name, cp.simplex_name_verification, cp.simplex_name_proof,
|
||||
cp.contact_domain, cp.contact_domain_proof, cp.contact_domain_verified,
|
||||
-- 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,
|
||||
@@ -1825,7 +1824,7 @@ Query:
|
||||
UPDATE group_profiles
|
||||
SET display_name = ?, full_name = ?, short_descr = ?, description = ?, image = ?,
|
||||
group_type = ?, group_link = ?,
|
||||
group_web_page = ?, simplex_name = ?, domain_web_page = ?, allow_embedding = ?, simplex_name_proof = ?,
|
||||
group_web_page = ?, group_domain = ?, domain_web_page = ?, allow_embedding = ?, group_domain_proof = ?,
|
||||
preferences = ?, member_admission = ?, updated_at = ?
|
||||
WHERE group_profile_id IN (
|
||||
SELECT group_profile_id
|
||||
@@ -2012,7 +2011,7 @@ Query:
|
||||
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_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx,
|
||||
cp.simplex_name, cp.simplex_name_verification, cp.simplex_name_proof,
|
||||
cp.contact_domain, cp.contact_domain_proof, cp.contact_domain_verified,
|
||||
-- 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,
|
||||
@@ -2098,7 +2097,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
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
|
||||
@@ -2128,7 +2127,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
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
|
||||
@@ -2158,7 +2157,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
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
|
||||
@@ -3689,7 +3688,7 @@ SEARCH connections USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
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, -- , ct.user_preferences
|
||||
cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx, cp.simplex_name, cp.simplex_name_verification, cp.simplex_name_proof
|
||||
cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx, cp.contact_domain, cp.contact_domain_proof, cp.contact_domain_verified
|
||||
FROM contact_profiles cp
|
||||
WHERE cp.user_id = ? AND cp.contact_profile_id = ?
|
||||
|
||||
@@ -3712,7 +3711,7 @@ SEARCH p USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT ct.contact_id, ct.conn_full_link_to_connect, ct.conn_short_link_to_connect FROM contacts ct
|
||||
JOIN contact_profiles cp ON cp.contact_profile_id = ct.contact_profile_id
|
||||
WHERE ct.user_id = ? AND cp.simplex_name = ? AND cp.simplex_name_verification = 1 AND ct.deleted = 0
|
||||
WHERE ct.user_id = ? AND cp.contact_domain = ? AND cp.contact_domain_verified = 1 AND ct.deleted = 0
|
||||
|
||||
Plan:
|
||||
SEARCH ct USING INDEX idx_contacts_chat_ts (user_id=?)
|
||||
@@ -3741,7 +3740,7 @@ SEARCH f USING PRIMARY KEY (file_id=?)
|
||||
SEARCH d USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT display_name, full_name, short_descr, image, contact_link, chat_peer_type, simplex_name, preferences
|
||||
SELECT display_name, full_name, short_descr, image, contact_link, chat_peer_type, contact_domain, preferences
|
||||
FROM contact_profiles
|
||||
WHERE user_id = ?
|
||||
|
||||
@@ -3796,7 +3795,7 @@ SEARCH files USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT g.group_id, g.conn_full_link_to_connect, g.conn_short_link_to_connect FROM groups g
|
||||
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
|
||||
WHERE g.user_id = ? AND gp.simplex_name = ? AND g.simplex_name_verification = 1
|
||||
WHERE g.user_id = ? AND gp.group_domain = ? AND g.group_domain_verified = 1
|
||||
|
||||
Plan:
|
||||
SEARCH g USING INDEX sqlite_autoindex_groups_2 (user_id=?)
|
||||
@@ -3804,7 +3803,7 @@ SEARCH gp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
SELECT g.group_id, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof
|
||||
FROM groups g
|
||||
JOIN group_profiles gp ON gp.group_profile_id = g.group_profile_id
|
||||
JOIN group_members mu ON mu.group_id = g.group_id AND mu.contact_id = ?
|
||||
@@ -5145,8 +5144,7 @@ Query:
|
||||
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_extra = ?, badge_master_key = ?, badge_signature = ?, badge_key_idx = ?,
|
||||
simplex_name = ?,
|
||||
simplex_name_proof = ?
|
||||
contact_domain = ?, contact_domain_proof = ?
|
||||
WHERE user_id = ? AND contact_profile_id = ?
|
||||
|
||||
Plan:
|
||||
@@ -5156,8 +5154,7 @@ Query:
|
||||
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_extra = ?, badge_master_key = ?, badge_signature = ?, badge_key_idx = ?,
|
||||
simplex_name = ?,
|
||||
simplex_name_proof = ?
|
||||
contact_domain = ?, contact_domain_proof = ?
|
||||
WHERE user_id = ? AND contact_profile_id = ?
|
||||
|
||||
Plan:
|
||||
@@ -5167,8 +5164,7 @@ Query:
|
||||
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_extra = ?, badge_master_key = ?, badge_signature = ?, badge_key_idx = ?,
|
||||
simplex_name = ?,
|
||||
simplex_name_proof = ?
|
||||
contact_domain = ?, contact_domain_proof = ?
|
||||
WHERE user_id = ? AND contact_profile_id = ?
|
||||
|
||||
Plan:
|
||||
@@ -5183,7 +5179,7 @@ Plan:
|
||||
SEARCH contact_profiles USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query:
|
||||
UPDATE contact_profiles SET simplex_name_verification = ?
|
||||
UPDATE contact_profiles SET contact_domain_verified = ?
|
||||
WHERE contact_profile_id IN (SELECT contact_profile_id FROM contacts WHERE user_id = ? AND contact_id = ?)
|
||||
|
||||
Plan:
|
||||
@@ -5517,20 +5513,19 @@ Query:
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof,
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.use_relays, g.relay_own_status,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri, g.group_domain_verified,
|
||||
g.root_priv_key, g.root_pub_key, g.member_priv_key,
|
||||
g.simplex_name_verification,
|
||||
-- GroupMember - membership
|
||||
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_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.simplex_name, pu.simplex_name_verification, pu.simplex_name_proof,
|
||||
pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, pu.badge_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.contact_domain, pu.contact_domain_proof, pu.contact_domain_verified,
|
||||
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
|
||||
|
||||
@@ -5556,20 +5551,19 @@ Query:
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof,
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.use_relays, g.relay_own_status,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri, g.group_domain_verified,
|
||||
g.root_priv_key, g.root_pub_key, g.member_priv_key,
|
||||
g.simplex_name_verification,
|
||||
-- GroupMember - membership
|
||||
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_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.simplex_name, pu.simplex_name_verification, pu.simplex_name_proof,
|
||||
pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, pu.badge_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.contact_domain, pu.contact_domain_proof, pu.contact_domain_verified,
|
||||
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
|
||||
|
||||
@@ -5588,20 +5582,19 @@ Query:
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof,
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.use_relays, g.relay_own_status,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri, g.group_domain_verified,
|
||||
g.root_priv_key, g.root_pub_key, g.member_priv_key,
|
||||
g.simplex_name_verification,
|
||||
-- GroupMember - membership
|
||||
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_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.simplex_name, pu.simplex_name_verification, pu.simplex_name_proof,
|
||||
pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, pu.badge_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.contact_domain, pu.contact_domain_proof, pu.contact_domain_verified,
|
||||
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
|
||||
|
||||
@@ -5625,7 +5618,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx,
|
||||
p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
FROM contact_requests cr
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
WHERE cr.business_group_id = ?
|
||||
@@ -5642,7 +5635,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx,
|
||||
p.simplex_name, p.simplex_name_verification, p.simplex_name_proof
|
||||
p.contact_domain, p.contact_domain_proof, p.contact_domain_verified
|
||||
FROM contact_requests cr
|
||||
JOIN contact_profiles p USING (contact_profile_id)
|
||||
WHERE cr.user_id = ? AND cr.contact_request_id = ?
|
||||
@@ -5654,7 +5647,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5682,7 +5675,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5703,7 +5696,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5723,7 +5716,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5743,7 +5736,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5763,7 +5756,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5783,7 +5776,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5803,7 +5796,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5823,7 +5816,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5843,7 +5836,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5863,7 +5856,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5883,7 +5876,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5903,7 +5896,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5923,7 +5916,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -5943,7 +5936,7 @@ Query:
|
||||
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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -6144,7 +6137,7 @@ SEARCH server_operators USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6157,7 +6150,7 @@ SEARCH ucp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6171,7 +6164,7 @@ SEARCH ucp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6185,7 +6178,7 @@ SEARCH ucp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6200,7 +6193,7 @@ SEARCH ucp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6214,7 +6207,7 @@ SEARCH ucp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6228,7 +6221,7 @@ SEARCH ucp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6242,7 +6235,7 @@ SEARCH ucp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6256,7 +6249,7 @@ SEARCH ucp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6269,7 +6262,7 @@ SEARCH ucp USING INTEGER PRIMARY KEY (rowid=?)
|
||||
Query:
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
@@ -6902,7 +6895,7 @@ Query: INSERT INTO contact_profiles (display_name, full_name, short_descr, image
|
||||
Plan:
|
||||
SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
Query: 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, badge_master_key, badge_signature, badge_key_idx, simplex_name, simplex_name_proof) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
Query: 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, badge_master_key, badge_signature, badge_key_idx, contact_domain, contact_domain_proof) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||
Plan:
|
||||
SEARCH contact_requests USING COVERING INDEX idx_contact_requests_contact_profile_id (contact_profile_id=?)
|
||||
|
||||
@@ -7480,14 +7473,14 @@ Query: UPDATE connections_sync SET should_sync = 1 WHERE connections_sync_id = 1
|
||||
Plan:
|
||||
SEARCH connections_sync USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE contact_profiles SET contact_domain = ?, updated_at = ? WHERE user_id = ? AND contact_profile_id = ?
|
||||
Plan:
|
||||
SEARCH contact_profiles USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE contact_profiles SET image = ? WHERE display_name = ?
|
||||
Plan:
|
||||
SEARCH contact_profiles USING INDEX contact_profiles_index (display_name=?)
|
||||
|
||||
Query: UPDATE contact_profiles SET simplex_name = ?, updated_at = ? WHERE user_id = ? AND contact_profile_id = ?
|
||||
Plan:
|
||||
SEARCH contact_profiles USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE contact_requests SET business_group_id = ? WHERE contact_request_id = ?
|
||||
Plan:
|
||||
SEARCH contact_requests USING INTEGER PRIMARY KEY (rowid=?)
|
||||
@@ -7688,6 +7681,14 @@ Query: UPDATE groups SET enable_ntfs = ?, send_rcpts = ?, favorite = ? WHERE use
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE groups SET group_domain_verified = ? WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE groups SET group_domain_verified = NULL WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE groups SET local_alias = ?, updated_at = ? WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
@@ -7732,14 +7733,6 @@ Query: UPDATE groups SET send_rcpts = NULL
|
||||
Plan:
|
||||
SCAN groups
|
||||
|
||||
Query: UPDATE groups SET simplex_name_verification = ? WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE groups SET simplex_name_verification = NULL WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
Query: UPDATE groups SET ui_themes = ?, updated_at = ? WHERE user_id = ? AND group_id = ?
|
||||
Plan:
|
||||
SEARCH groups USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|
||||
@@ -29,9 +29,9 @@ CREATE TABLE contact_profiles(
|
||||
badge_master_key BLOB,
|
||||
badge_signature BLOB,
|
||||
badge_key_idx INTEGER,
|
||||
simplex_name TEXT,
|
||||
simplex_name_verification INTEGER,
|
||||
simplex_name_proof TEXT
|
||||
contact_domain TEXT,
|
||||
contact_domain_proof TEXT,
|
||||
contact_domain_verified INTEGER
|
||||
) STRICT;
|
||||
CREATE TABLE users(
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
@@ -140,10 +140,10 @@ CREATE TABLE group_profiles(
|
||||
group_link BLOB,
|
||||
public_group_id BLOB,
|
||||
group_web_page TEXT,
|
||||
group_domain TEXT,
|
||||
domain_web_page INTEGER,
|
||||
allow_embedding INTEGER,
|
||||
simplex_name TEXT,
|
||||
simplex_name_proof TEXT
|
||||
group_domain_proof TEXT
|
||||
) STRICT;
|
||||
CREATE TABLE groups(
|
||||
group_id INTEGER PRIMARY KEY, -- local group ID
|
||||
@@ -204,7 +204,7 @@ CREATE TABLE groups(
|
||||
roster_sending_owner_gm_id INTEGER,
|
||||
roster_broker_ts TEXT,
|
||||
roster_blob BLOB,
|
||||
simplex_name_verification INTEGER, -- received
|
||||
group_domain_verified INTEGER, -- received
|
||||
FOREIGN KEY(user_id, local_display_name)
|
||||
REFERENCES display_names(user_id, local_display_name)
|
||||
ON DELETE CASCADE
|
||||
|
||||
@@ -33,14 +33,14 @@ import qualified Data.Text as T
|
||||
import Data.Time.Clock (UTCTime (..), getCurrentTime)
|
||||
import Data.Type.Equality
|
||||
import Simplex.Chat.Badges (BadgeRow, badgeToRow, rowToBadge, verifyBadge_)
|
||||
import Simplex.Chat.Names (NameClaimProof, claimName, claimProof, mkSimplexNameClaim)
|
||||
import Simplex.Chat.Names (SimplexDomainProof, SimplexDomainClaim (..), claimDomain)
|
||||
import Simplex.Chat.Messages
|
||||
import Simplex.Chat.Remote.Types
|
||||
import Simplex.Chat.Types
|
||||
import Simplex.Chat.Types.Preferences
|
||||
import Simplex.Chat.Types.Shared
|
||||
import Simplex.Chat.Types.UITheme
|
||||
import Simplex.Messaging.Agent.Protocol (AConnShortLink (..), AConnectionRequestUri (..), ACreatedConnLink (..), ConnId, ConnShortLink, ConnectionRequestUri, CreatedConnLink (..), SimplexNameInfo, UserId, connMode)
|
||||
import Simplex.Messaging.Agent.Protocol (AConnShortLink (..), AConnectionRequestUri (..), ACreatedConnLink (..), ConnId, ConnShortLink, ConnectionRequestUri, CreatedConnLink (..), SimplexDomain, UserId, connMode)
|
||||
import Simplex.Messaging.Agent.Store (AnyStoreError (..))
|
||||
import Simplex.Messaging.Agent.Store.AgentStore (firstRow, maybeFirstRow)
|
||||
import Simplex.Messaging.Agent.Store.Common (withSavepoint)
|
||||
@@ -49,6 +49,7 @@ import qualified Simplex.Messaging.Agent.Store.DB as DB
|
||||
import qualified Simplex.Messaging.Crypto as C
|
||||
import Simplex.Messaging.Crypto.Ratchet (PQEncryption (..), PQSupport (..))
|
||||
import qualified Simplex.Messaging.Crypto.Ratchet as CR
|
||||
import Simplex.Messaging.Encoding.String (StrJSON (..))
|
||||
import Simplex.Messaging.Parsers (dropPrefix, sumTypeJSON)
|
||||
import Simplex.Messaging.Protocol (SubscriptionMode (..))
|
||||
import Simplex.Messaging.Util (AnyError (..))
|
||||
@@ -414,13 +415,13 @@ createContact db cxt user profile = do
|
||||
void $ createContact_ db cxt user profile emptyChatPrefs Nothing "" currentTs
|
||||
|
||||
createContact_ :: DB.Connection -> StoreCxt -> User -> Profile -> Preferences -> Maybe (ACreatedConnLink, Maybe SharedMsgId) -> LocalAlias -> UTCTime -> ExceptT StoreError IO ContactId
|
||||
createContact_ db cxt User {userId} Profile {displayName, fullName, shortDescr, image, contactLink, simplexName, peerType, badge, preferences} ctUserPreferences prepared localAlias currentTs =
|
||||
createContact_ db cxt User {userId} Profile {displayName, fullName, shortDescr, image, contactLink, contactDomain, peerType, badge, preferences} ctUserPreferences prepared localAlias currentTs =
|
||||
ExceptT . withLocalDisplayName db userId displayName $ \ldn -> do
|
||||
badgeVerified <- verifyBadge_ (badgeKeys cxt) 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, badge_extra, badge_master_key, badge_signature, badge_key_idx, simplex_name, simplex_name_proof) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
|
||||
((displayName, fullName, shortDescr, image, contactLink, peerType) :. (userId, localAlias, preferences, currentTs, currentTs) :. badgeToRow badge badgeVerified :. (claimName <$> simplexName, claimProof =<< simplexName))
|
||||
"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, badge_master_key, badge_signature, badge_key_idx, contact_domain, contact_domain_proof) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
|
||||
((displayName, fullName, shortDescr, image, contactLink, peerType) :. (userId, localAlias, preferences, currentTs, currentTs) :. badgeToRow badge badgeVerified :. contactDomainToRow contactDomain)
|
||||
profileId <- insertedRowId db
|
||||
DB.execute
|
||||
db
|
||||
@@ -487,13 +488,15 @@ type PreparedContactRow = (Maybe AConnectionRequestUri, Maybe AConnShortLink, Ma
|
||||
|
||||
type GroupDirectInvitationRow = (Maybe ConnReqInvitation, Maybe GroupId, Maybe GroupMemberId, Maybe Int64, BoolInt)
|
||||
|
||||
type ContactRow' = (ProfileId, ContactName, ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, LocalAlias, BoolInt, ContactStatus) :. (Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime) :. PreparedContactRow :. (Maybe Int64, Maybe GroupMemberId, BoolInt) :. GroupDirectInvitationRow :. (Maybe UIThemeEntityOverrides, BoolInt, Maybe CustomData, Maybe Int64) :. BadgeRow :. (Maybe SimplexNameInfo, Maybe BoolInt, Maybe NameClaimProof)
|
||||
type ContactRow' = (ProfileId, ContactName, ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, LocalAlias, BoolInt, ContactStatus) :. (Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe Preferences, Preferences, UTCTime, UTCTime, Maybe UTCTime) :. PreparedContactRow :. (Maybe Int64, Maybe GroupMemberId, BoolInt) :. GroupDirectInvitationRow :. (Maybe UIThemeEntityOverrides, BoolInt, Maybe CustomData, Maybe Int64) :. BadgeRow :. ContactDomainRow
|
||||
|
||||
type ContactRow = Only ContactId :. ContactRow'
|
||||
|
||||
type ContactDomainRow = (Maybe SimplexDomain, Maybe SimplexDomainProof, Maybe BoolInt)
|
||||
|
||||
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 :. (cpsimplexName, cpContactNameVerification, cpsimplexNameProof)) :. connRow) =
|
||||
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim cpsimplexName cpsimplexNameProof, simplexNameVerification = unBI <$> cpContactNameVerification, 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 :. domainRow) :. connRow) =
|
||||
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, contactDomain = rowToContactDomain domainRow, contactDomainVerified = rowToDomainVerified domainRow, 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
|
||||
@@ -502,6 +505,15 @@ toContact now cxt user chatTags ((Only contactId :. (profileId, localDisplayName
|
||||
groupDirectInv = toGroupDirectInvitation groupDirectInvRow
|
||||
in Contact {contactId, localDisplayName, profile, activeConn, contactUsed, contactStatus, chatSettings, userPreferences, mergedPreferences, createdAt, updatedAt, chatTs, preparedContact, contactRequestId, contactGroupMemberId, contactGrpInvSent, groupDirectInv, chatTags, chatItemTTL, uiThemes, chatDeleted, customData}
|
||||
|
||||
rowToContactDomain :: ContactDomainRow -> Maybe SimplexDomainClaim
|
||||
rowToContactDomain (domain_, domainProof_, _) = (`SimplexDomainClaim` domainProof_) . StrJSON <$> domain_
|
||||
|
||||
rowToDomainVerified :: ContactDomainRow -> Maybe Bool
|
||||
rowToDomainVerified (_, _, domainVerification_) = unBI <$> domainVerification_
|
||||
|
||||
contactDomainToRow :: Maybe SimplexDomainClaim -> (Maybe SimplexDomain, Maybe SimplexDomainProof)
|
||||
contactDomainToRow d = (claimDomain <$> d, proof =<< d)
|
||||
|
||||
toPreparedContact :: PreparedContactRow -> Maybe PreparedContact
|
||||
toPreparedContact (connFullLink, connShortLink, welcomeSharedMsgId, requestSharedMsgId) =
|
||||
(\cl@(ACCL m _) -> PreparedContact {connLinkToConnect = cl, uiConnLinkType = connMode m, welcomeSharedMsgId, requestSharedMsgId})
|
||||
@@ -526,17 +538,17 @@ 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, -- , ct.user_preferences
|
||||
cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx, cp.simplex_name, cp.simplex_name_verification, cp.simplex_name_proof
|
||||
cp.badge_proof, cp.badge_pres_header, cp.badge_expiry, cp.badge_type, cp.badge_verified, cp.badge_extra, cp.badge_master_key, cp.badge_signature, cp.badge_key_idx, cp.contact_domain, cp.contact_domain_proof, cp.contact_domain_verified
|
||||
FROM contact_profiles cp
|
||||
WHERE cp.user_id = ? AND cp.contact_profile_id = ?
|
||||
|]
|
||||
(userId, profileId)
|
||||
|
||||
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)
|
||||
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 :. ContactDomainRow
|
||||
|
||||
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 :. (simplexName, simplexNameVerification, simplexNameProof)) = do
|
||||
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim simplexName simplexNameProof, simplexNameVerification = unBI <$> simplexNameVerification, 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 :. domainRow) = do
|
||||
let profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, contactDomain = rowToContactDomain domainRow, contactDomainVerified = rowToDomainVerified domainRow, 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}
|
||||
|
||||
@@ -545,17 +557,17 @@ userQuery =
|
||||
[sql|
|
||||
SELECT u.user_id, u.agent_user_id, u.contact_id, ucp.contact_profile_id, u.active_user, u.active_order, u.local_display_name, ucp.full_name, ucp.short_descr, ucp.image, ucp.contact_link, ucp.chat_peer_type, ucp.preferences,
|
||||
u.show_ntfs, u.send_rcpts_contacts, u.send_rcpts_small_groups, u.auto_accept_member_contacts, u.view_pwd_hash, u.view_pwd_salt, u.user_member_profile_updated_at, u.is_user_chat_relay, u.client_service, u.ui_themes,
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.simplex_name, ucp.simplex_name_verification, ucp.simplex_name_proof
|
||||
ucp.badge_proof, ucp.badge_pres_header, ucp.badge_expiry, ucp.badge_type, ucp.badge_verified, ucp.badge_extra, ucp.badge_master_key, ucp.badge_signature, ucp.badge_key_idx, ucp.contact_domain, ucp.contact_domain_proof, ucp.contact_domain_verified
|
||||
FROM users u
|
||||
JOIN contacts uct ON uct.contact_id = u.contact_id
|
||||
JOIN contact_profiles ucp ON ucp.contact_profile_id = uct.contact_profile_id
|
||||
|]
|
||||
|
||||
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 :. (simplexName, simplexNameVerification, simplexNameProof)) =
|
||||
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 :. ContactDomainRow -> 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 :. domainRow) =
|
||||
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 simplexName simplexNameProof, simplexNameVerification = unBI <$> simplexNameVerification, peerType, localBadge = rowToBadge now badgeRow, preferences = userPreferences, localAlias = ""}
|
||||
profile = LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, contactDomain = rowToContactDomain domainRow, contactDomainVerified = rowToDomainVerified domainRow, peerType, localBadge = rowToBadge now badgeRow, preferences = userPreferences, localAlias = ""}
|
||||
fullPreferences = fullPreferences' userPreferences
|
||||
viewPwdHash = UserPwdHash <$> viewPwdHash_ <*> viewPwdSalt_
|
||||
|
||||
@@ -671,16 +683,16 @@ type BusinessChatInfoRow = (Maybe BusinessChatType, Maybe MemberId, Maybe Member
|
||||
|
||||
type GroupKeysRow = (Maybe C.PrivateKeyEd25519, Maybe C.PublicKeyEd25519, Maybe C.PrivateKeyEd25519)
|
||||
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Text, Maybe Text, Maybe ImageData, Maybe GroupType, Maybe ShortLinkContact, Maybe B64UrlByteString) :. PublicGroupAccessRow :. (Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. PreparedGroupRow :. BusinessChatInfoRow :. (BoolInt, Maybe RelayStatus, Maybe UIThemeEntityOverrides, Int64, Maybe Int64, Maybe VersionRoster, Maybe CustomData, Maybe Int64, Int, Maybe ConnReqContact) :. GroupKeysRow :. Only (Maybe BoolInt) :. GroupMemberRow
|
||||
type GroupInfoRow = (Int64, GroupName, GroupName, Text, Maybe Text, Text, Maybe Text, Maybe ImageData, Maybe GroupType, Maybe ShortLinkContact, Maybe B64UrlByteString) :. PublicGroupAccessRow :. (Maybe MsgFilter, Maybe BoolInt, BoolInt, Maybe GroupPreferences, Maybe GroupMemberAdmission) :. (UTCTime, UTCTime, Maybe UTCTime, Maybe UTCTime) :. PreparedGroupRow :. BusinessChatInfoRow :. (BoolInt, Maybe RelayStatus, Maybe UIThemeEntityOverrides, Int64, Maybe Int64, Maybe VersionRoster, Maybe CustomData, Maybe Int64, Int, Maybe ConnReqContact, Maybe BoolInt) :. GroupKeysRow :. GroupMemberRow
|
||||
|
||||
type PublicGroupAccessRow = (Maybe Text, Maybe SimplexNameInfo, Maybe BoolInt, Maybe BoolInt, Maybe NameClaimProof)
|
||||
type PublicGroupAccessRow = (Maybe Text, Maybe SimplexDomain, Maybe BoolInt, Maybe BoolInt, Maybe SimplexDomainProof)
|
||||
|
||||
type GroupMemberRow = (GroupMemberId, GroupId, Int64, MemberId, VersionChat, VersionChat, GroupMemberRole, GroupMemberCategory, GroupMemberStatus, BoolInt, Maybe MemberRestrictionStatus) :. (Maybe Int64, Maybe GroupMemberId, ContactName, Maybe ContactId, ProfileId) :. ProfileRow :. (UTCTime, UTCTime) :. (Maybe UTCTime, Int64, Int64, Int64, Maybe UTCTime, Maybe C.PublicKeyEd25519, Maybe ShortLinkContact)
|
||||
|
||||
type ProfileRow = (ProfileId, ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, LocalAlias, Maybe Preferences) :. BadgeRow :. (Maybe SimplexNameInfo, Maybe BoolInt, Maybe NameClaimProof)
|
||||
type ProfileRow = (ProfileId, ContactName, Text, Maybe Text, Maybe ImageData, Maybe ConnLinkContact, Maybe ChatPeerType, LocalAlias, Maybe Preferences) :. BadgeRow :. ContactDomainRow
|
||||
|
||||
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 simplexNameVerification :. 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, groupDomainVerified) :. groupKeysRow :. userMemberRow) =
|
||||
let membership = (toGroupMember now userContactId userMemberRow) {memberChatVRange = vr cxt}
|
||||
chatSettings = ChatSettings {enableNtfs = fromMaybe MFAll enableNtfs_, sendRcpts = unBI <$> sendRcpts, favorite}
|
||||
fullGroupPreferences = mergeGroupPreferences groupPreferences
|
||||
@@ -690,7 +702,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, simplexNameVerification = unBI <$> simplexNameVerification}
|
||||
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, groupDomainVerified = unBI <$> groupDomainVerified}
|
||||
|
||||
toPreparedGroup :: PreparedGroupRow -> Maybe PreparedGroup
|
||||
toPreparedGroup = \case
|
||||
@@ -705,14 +717,14 @@ toPublicGroupProfile _ _ _ _ = Nothing
|
||||
|
||||
publicGroupAccessRow :: Maybe PublicGroupProfile -> PublicGroupAccessRow
|
||||
publicGroupAccessRow pgp = case pgp >>= publicGroupAccess of
|
||||
Just PublicGroupAccess {groupWebPage, simplexName, domainWebPage, allowEmbedding} ->
|
||||
(groupWebPage, claimName <$> simplexName, Just (BI domainWebPage), Just (BI allowEmbedding), claimProof =<< simplexName)
|
||||
Just PublicGroupAccess {groupWebPage, groupDomainClaim, domainWebPage, allowEmbedding} ->
|
||||
(groupWebPage, claimDomain <$> groupDomainClaim, Just (BI domainWebPage), Just (BI allowEmbedding), proof =<< groupDomainClaim)
|
||||
Nothing -> (Nothing, Nothing, Nothing, Nothing, Nothing)
|
||||
|
||||
toPublicGroupAccess :: PublicGroupAccessRow -> Maybe PublicGroupAccess
|
||||
toPublicGroupAccess (groupWebPage, simplexName, domainWebPage_, allowEmbedding_, simplexNameProof)
|
||||
| isJust groupWebPage || isJust simplexName || domainWebPage || allowEmbedding =
|
||||
Just PublicGroupAccess {groupWebPage, simplexName = mkSimplexNameClaim simplexName simplexNameProof, domainWebPage, allowEmbedding}
|
||||
toPublicGroupAccess (groupWebPage, groupDomain_, domainWebPage_, allowEmbedding_, groupDomainProof_)
|
||||
| isJust groupWebPage || isJust groupDomain_ || domainWebPage || allowEmbedding =
|
||||
Just PublicGroupAccess {groupWebPage, groupDomainClaim = (`SimplexDomainClaim` groupDomainProof_) . StrJSON <$> groupDomain_, domainWebPage, allowEmbedding}
|
||||
| otherwise = Nothing
|
||||
where
|
||||
domainWebPage = maybe False unBI domainWebPage_
|
||||
@@ -751,7 +763,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_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.simplex_name, p.simplex_name_verification, p.simplex_name_proof,
|
||||
p.badge_proof, p.badge_pres_header, p.badge_expiry, p.badge_type, p.badge_verified, p.badge_extra, p.badge_master_key, p.badge_signature, p.badge_key_idx, p.contact_domain, p.contact_domain_proof, p.contact_domain_verified,
|
||||
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,
|
||||
@@ -768,8 +780,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 :. (simplexName, simplexNameVerification, simplexNameProof)) =
|
||||
LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, simplexName = mkSimplexNameClaim simplexName simplexNameProof, simplexNameVerification = unBI <$> simplexNameVerification, peerType, localBadge = rowToBadge now badgeRow, localAlias, preferences}
|
||||
rowToLocalProfile now ((profileId, displayName, fullName, shortDescr, image, contactLink, peerType, localAlias, preferences) :. badgeRow :. domainRow) =
|
||||
LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, contactDomain = rowToContactDomain domainRow, contactDomainVerified = rowToDomainVerified domainRow, peerType, localBadge = rowToBadge now badgeRow, localAlias, preferences}
|
||||
|
||||
toBusinessChatInfo :: BusinessChatInfoRow -> Maybe BusinessChatInfo
|
||||
toBusinessChatInfo (Just chatType, Just businessId, Just customerId) = Just BusinessChatInfo {chatType, businessId, customerId}
|
||||
@@ -784,20 +796,19 @@ groupInfoQueryFields =
|
||||
SELECT
|
||||
-- GroupInfo
|
||||
g.group_id, g.local_display_name, gp.display_name, gp.full_name, gp.short_descr, g.local_alias, gp.description, gp.image, gp.group_type, gp.group_link, gp.public_group_id,
|
||||
gp.group_web_page, gp.simplex_name, gp.domain_web_page, gp.allow_embedding, gp.simplex_name_proof,
|
||||
gp.group_web_page, gp.group_domain, gp.domain_web_page, gp.allow_embedding, gp.group_domain_proof,
|
||||
g.enable_ntfs, g.send_rcpts, g.favorite, gp.preferences, gp.member_admission,
|
||||
g.created_at, g.updated_at, g.chat_ts, g.user_member_profile_sent_at,
|
||||
g.conn_full_link_to_connect, g.conn_short_link_to_connect, g.conn_link_prepared_connection, g.conn_link_started_connection, g.welcome_shared_msg_id, g.request_shared_msg_id,
|
||||
g.business_chat, g.business_member_id, g.customer_member_id,
|
||||
g.use_relays, g.relay_own_status,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri,
|
||||
g.ui_themes, g.summary_current_members_count, g.public_member_count, g.roster_version, g.custom_data, g.chat_item_ttl, g.members_require_attention, g.via_group_link_uri, g.group_domain_verified,
|
||||
g.root_priv_key, g.root_pub_key, g.member_priv_key,
|
||||
g.simplex_name_verification,
|
||||
-- GroupMember - membership
|
||||
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_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.simplex_name, pu.simplex_name_verification, pu.simplex_name_proof,
|
||||
pu.badge_proof, pu.badge_pres_header, pu.badge_expiry, pu.badge_type, pu.badge_verified, pu.badge_extra, pu.badge_master_key, pu.badge_signature, pu.badge_key_idx, pu.contact_domain, pu.contact_domain_proof, pu.contact_domain_verified,
|
||||
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
|
||||
|]
|
||||
|
||||
+12
-16
@@ -53,7 +53,7 @@ import Data.Type.Equality (testEquality, (:~:) (Refl))
|
||||
import Data.Typeable (Typeable)
|
||||
import Data.Word (Word16)
|
||||
import Simplex.Chat.Badges (BadgeInfo (..), BadgeProof (..), BadgeStatus (..), LocalBadge (..), localBadgeInfo, localBadgeStatus, mkBadgeStatus, verifyBadge)
|
||||
import Simplex.Chat.Names (SimplexNameClaim, setClaimProof)
|
||||
import Simplex.Chat.Names (SimplexDomainClaim (..))
|
||||
import Simplex.Messaging.Crypto.BBS (BBSPublicKey)
|
||||
import Simplex.Chat.Types.Preferences
|
||||
import Simplex.Chat.Types.Shared
|
||||
@@ -499,7 +499,7 @@ data GroupInfo = GroupInfo
|
||||
membersRequireAttention :: Int,
|
||||
viaGroupLinkUri :: Maybe ConnReqContact,
|
||||
groupKeys :: Maybe GroupKeys,
|
||||
simplexNameVerification :: Maybe Bool
|
||||
groupDomainVerified :: Maybe Bool
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
@@ -699,7 +699,7 @@ data Profile = Profile
|
||||
preferences :: Maybe Preferences,
|
||||
peerType :: Maybe ChatPeerType,
|
||||
badge :: Maybe BadgeProof,
|
||||
simplexName :: Maybe SimplexNameClaim
|
||||
contactDomain :: Maybe SimplexDomainClaim
|
||||
-- fields that should not be read into this data type to prevent sending them as part of profile to contacts:
|
||||
-- - contact_profile_id
|
||||
-- - incognito
|
||||
@@ -732,7 +732,7 @@ instance TextEncoding ChatPeerType where
|
||||
|
||||
profileFromName :: ContactName -> Profile
|
||||
profileFromName displayName =
|
||||
Profile {displayName, fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, preferences = Nothing, peerType = Nothing, badge = Nothing, simplexName = Nothing}
|
||||
Profile {displayName, fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, preferences = Nothing, peerType = Nothing, badge = Nothing, contactDomain = Nothing}
|
||||
|
||||
-- check if profiles match ignoring preferences
|
||||
profilesMatch :: LocalProfile -> LocalProfile -> Bool
|
||||
@@ -747,7 +747,7 @@ sameProfileContent :: Profile -> Profile -> Bool
|
||||
sameProfileContent p@Profile {badge = b} p'@Profile {badge = b'} =
|
||||
clearProofs p == clearProofs p' && (proofInfo <$> b) == (proofInfo <$> b')
|
||||
where
|
||||
clearProofs pr@Profile {simplexName} = pr {badge = Nothing, simplexName = setClaimProof Nothing <$> simplexName}
|
||||
clearProofs pr@Profile {contactDomain} = pr {badge = Nothing, contactDomain = (\d -> d {proof = Nothing} :: SimplexDomainClaim) <$> contactDomain}
|
||||
proofInfo :: BadgeProof -> BadgeInfo
|
||||
proofInfo (BadgeProof _ _ _ info) = info
|
||||
|
||||
@@ -784,8 +784,8 @@ data LocalProfile = LocalProfile
|
||||
peerType :: Maybe ChatPeerType,
|
||||
localBadge :: Maybe LocalBadge,
|
||||
localAlias :: LocalAlias,
|
||||
simplexName :: Maybe SimplexNameClaim,
|
||||
simplexNameVerification :: Maybe Bool
|
||||
contactDomain :: Maybe SimplexDomainClaim,
|
||||
contactDomainVerified :: Maybe Bool
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
@@ -793,15 +793,15 @@ 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 simplexNameVerification =
|
||||
LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, preferences, peerType, localBadge, localAlias, simplexName, simplexNameVerification}
|
||||
toLocalProfile profileId Profile {displayName, fullName, shortDescr, image, contactLink, preferences, peerType, badge, contactDomain} localAlias now badgeVerified contactDomainVerified =
|
||||
LocalProfile {profileId, displayName, fullName, shortDescr, image, contactLink, preferences, peerType, localBadge, localAlias, contactDomain, contactDomainVerified}
|
||||
where
|
||||
localBadge = (\b@(BadgeProof _ _ _ info) -> PeerBadge b (mkBadgeStatus now badgeVerified info)) <$> badge
|
||||
|
||||
fromLocalProfile :: LocalProfile -> Profile
|
||||
fromLocalProfile LocalProfile {displayName, fullName, shortDescr, image, contactLink, preferences, peerType, localBadge, simplexName} =
|
||||
fromLocalProfile LocalProfile {displayName, fullName, shortDescr, image, contactLink, preferences, peerType, localBadge, contactDomain} =
|
||||
-- the name proof is re-signed on each send
|
||||
Profile {displayName, fullName, shortDescr, image, contactLink, preferences, peerType, badge = localBadge >>= wireBadge, simplexName = setClaimProof Nothing <$> simplexName}
|
||||
Profile {displayName, fullName, shortDescr, image, contactLink, preferences, peerType, badge = localBadge >>= wireBadge, contactDomain = (\d -> d {proof = Nothing} :: SimplexDomainClaim) <$> contactDomain}
|
||||
where
|
||||
wireBadge :: LocalBadge -> Maybe BadgeProof
|
||||
wireBadge = \case
|
||||
@@ -846,16 +846,12 @@ instance ToField GroupType where toField = toField . textEncode
|
||||
|
||||
data PublicGroupAccess = PublicGroupAccess
|
||||
{ groupWebPage :: Maybe Text,
|
||||
simplexName :: Maybe SimplexNameClaim,
|
||||
groupDomainClaim :: Maybe SimplexDomainClaim,
|
||||
domainWebPage :: Bool,
|
||||
allowEmbedding :: Bool
|
||||
}
|
||||
deriving (Eq, Show)
|
||||
|
||||
-- selector disambiguated from Profile/LocalProfile simplexName
|
||||
publicGroupClaim :: PublicGroupAccess -> Maybe SimplexNameClaim
|
||||
publicGroupClaim PublicGroupAccess {simplexName} = simplexName
|
||||
|
||||
data PublicGroupProfile = PublicGroupProfile
|
||||
{ groupType :: GroupType,
|
||||
groupLink :: ShortLinkContact,
|
||||
|
||||
+42
-41
@@ -52,7 +52,7 @@ import Simplex.Chat.Remote.AppVersion (AppVersion (..), pattern AppVersionRange)
|
||||
import Simplex.Chat.Remote.Types
|
||||
import Simplex.Chat.Store (AddressSettings (..), AutoAccept (..), StoreError (..), UserContactLink (..))
|
||||
import Simplex.Chat.Styled
|
||||
import Simplex.Chat.Names (claimName, claimProof)
|
||||
import Simplex.Chat.Names (SimplexDomainClaim (..), claimDomain)
|
||||
import Simplex.Chat.Types
|
||||
import Simplex.Chat.Types.Preferences
|
||||
import Simplex.Chat.Types.Shared
|
||||
@@ -148,8 +148,8 @@ chatResponseToView hu cfg@ChatConfig {logLevel, showReactions, testView} liveIte
|
||||
CRContactRatchetSyncStarted {} -> ["connection synchronization started"]
|
||||
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 (groupSimplexName g) result
|
||||
CRContactNameVerified u (Contact {profile = LocalProfile {contactDomain}}) result -> ttyUser u $ viewNameVerified NTContact (claimDomain <$> contactDomain) result
|
||||
CRGroupNameVerified u g result -> ttyUser u $ viewNameVerified NTPublicGroup (groupSimplexDomain 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,13 +1128,13 @@ simplexChatContact' = \case
|
||||
CLFull (CRContactUri crData) -> CLFull $ CRContactUri crData {crScheme = simplexChat}
|
||||
l@(CLShort _) -> l
|
||||
|
||||
groupSimplexName :: GroupInfo -> Maybe SimplexNameInfo
|
||||
groupSimplexName GroupInfo {groupProfile = GroupProfile {publicGroup}} =
|
||||
claimName <$> (publicGroup >>= publicGroupAccess >>= publicGroupClaim)
|
||||
groupSimplexDomain :: GroupInfo -> Maybe SimplexDomain
|
||||
groupSimplexDomain GroupInfo {groupProfile = GroupProfile {publicGroup}} =
|
||||
claimDomain <$> (publicGroup >>= publicGroupAccess >>= groupDomainClaim)
|
||||
|
||||
viewNameVerified :: Maybe SimplexNameInfo -> Maybe Text -> [StyledString]
|
||||
viewNameVerified name_ result =
|
||||
let nameStr = maybe "name" (\ni -> "SimpleX name " <> shortNameInfoStr ni) name_
|
||||
viewNameVerified :: SimplexNameType -> Maybe SimplexDomain -> Maybe Text -> [StyledString]
|
||||
viewNameVerified nameType domain_ result =
|
||||
let nameStr = maybe "name" (\d -> "SimpleX name " <> shortNameInfoStr (SimplexNameInfo nameType d)) domain_
|
||||
in case result of
|
||||
Nothing -> [plain nameStr <> " verified"]
|
||||
Just reason -> [plain nameStr <> " not verified: " <> plain reason]
|
||||
@@ -1142,16 +1142,16 @@ viewNameVerified name_ result =
|
||||
-- §4.7: show a peer's claimed name only with its verification context — "verified" / "verification
|
||||
-- failed" when a status is recorded, "unverified" when there is a proof but no status yet, and nothing
|
||||
-- at all when there is neither (an unproven, unverifiable claim is not shown).
|
||||
simplexNameStatus :: Maybe SimplexNameInfo -> Maybe Bool -> Bool -> [StyledString]
|
||||
simplexNameStatus Nothing _ _ = []
|
||||
simplexNameStatus (Just ni) status hasProof = case status of
|
||||
simplexDomainLine :: SimplexNameType -> Maybe SimplexDomainClaim -> Maybe Bool -> [StyledString]
|
||||
simplexDomainLine _ Nothing _ = []
|
||||
simplexDomainLine nameType (Just SimplexDomainClaim {domain, proof}) status = case status of
|
||||
Just True -> [line "verified"]
|
||||
Just False -> [line "verification failed"]
|
||||
Nothing
|
||||
| hasProof -> [line "unverified"]
|
||||
| isJust proof -> [line "unverified"]
|
||||
| otherwise -> []
|
||||
where
|
||||
line s = "SimpleX name: " <> plain (shortNameInfoStr ni) <> " (" <> s <> ")"
|
||||
line s = plain $ "SimpleX name: " <> shortNameInfoStr (SimplexNameInfo nameType (unStrJSON domain)) <> " (" <> s <> ")"
|
||||
|
||||
-- TODO [short links] show all settings
|
||||
viewAddressSettings :: AddressSettings -> [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 <- [groupSimplexName g]]
|
||||
<> [plain ("SimpleX name: " <> shortNameInfoStr (SimplexNameInfo NTPublicGroup d)) | Just d <- [groupSimplexDomain 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 <- [groupSimplexName g]]
|
||||
<> [plain ("SimpleX name: " <> shortNameInfoStr (SimplexNameInfo NTPublicGroup d)) | Just d <- [groupSimplexDomain 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, simplexNameVerification}, activeConn, uiThemes, customData} stats incognitoProfile =
|
||||
viewContactInfo ct@Contact {contactId, profile = LocalProfile {localAlias, contactLink, localBadge, contactDomain, contactDomainVerified}, 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) simplexNameVerification (isJust (claimProof =<< simplexName))
|
||||
<> simplexDomainLine NTContact contactDomain contactDomainVerified
|
||||
<> maybe
|
||||
["you've shared main profile with this contact"]
|
||||
(\p -> ["you've shared incognito profile with this contact: " <> incognitoProfile' p])
|
||||
@@ -2049,10 +2049,10 @@ viewGroupUpdated
|
||||
access = pg >>= publicGroupAccess
|
||||
access' = pg' >>= publicGroupAccess
|
||||
viewAccess Nothing = " removed"
|
||||
viewAccess (Just PublicGroupAccess {groupWebPage, simplexName, domainWebPage, allowEmbedding}) =
|
||||
viewAccess (Just PublicGroupAccess {groupWebPage, groupDomainClaim, domainWebPage, allowEmbedding}) =
|
||||
maybe "" (\u -> " web=" <> plain u) groupWebPage
|
||||
<> maybe "" (\ni -> " name=" <> plain (strEncode ni)) (claimName <$> simplexName)
|
||||
<> (if domainWebPage then " name_page=on" else "")
|
||||
<> maybe "" (\ni -> " domain=" <> plain (strEncode ni)) (claimDomain <$> groupDomainClaim)
|
||||
<> (if domainWebPage then " domain_page=on" else "")
|
||||
<> (if allowEmbedding then " embed=on" else "")
|
||||
|
||||
viewGroupProfile :: GroupInfo -> [StyledString]
|
||||
@@ -2152,11 +2152,11 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
|
||||
ILPConnecting Nothing -> [invLink "connecting"]
|
||||
ILPConnecting (Just ct) -> [invLink ("connecting to contact " <> ttyContact' ct)]
|
||||
ILPKnown ct
|
||||
| nextConnectPrepared ct -> [invLink ("known prepared contact " <> ttyContact' ct)] <> contactNameLine ct
|
||||
| contactDeleted ct -> [invLink ("known deleted contact " <> ttyContact' ct)] <> contactNameLine ct
|
||||
| nextConnectPrepared ct -> [invLink ("known prepared contact " <> ttyContact' ct)] <> contactDomainLine ct
|
||||
| contactDeleted ct -> [invLink ("known deleted contact " <> ttyContact' ct)] <> contactDomainLine ct
|
||||
| otherwise ->
|
||||
[invLink ("known contact " <> ttyContact' ct)]
|
||||
<> contactNameLine ct
|
||||
<> contactDomainLine ct
|
||||
<> ["use " <> ttyToContact' ct <> highlight' "<message>" <> " to send messages"]
|
||||
where
|
||||
invLink = ("invitation link: " <>)
|
||||
@@ -2170,12 +2170,12 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
|
||||
CAPConnectingConfirmReconnect -> [ctAddr "connecting, allowed to reconnect"]
|
||||
CAPConnectingProhibit ct -> [ctAddr ("connecting to contact " <> ttyContact' ct)]
|
||||
CAPKnown ct
|
||||
| nextConnectPrepared ct -> [ctAddr ("known prepared contact " <> ttyContact' ct)] <> contactNameLine ct
|
||||
| nextConnectPrepared ct -> [ctAddr ("known prepared contact " <> ttyContact' ct)] <> contactDomainLine ct
|
||||
| otherwise ->
|
||||
[ctAddr ("known contact " <> ttyContact' ct)]
|
||||
<> contactNameLine ct
|
||||
<> contactDomainLine ct
|
||||
<> ["use " <> ttyToContact' ct <> highlight' "<message>" <> " to send messages"]
|
||||
CAPContactViaAddress ct -> [ctAddr ("known contact without connection " <> ttyContact' ct)] <> contactNameLine ct
|
||||
CAPContactViaAddress ct -> [ctAddr ("known contact without connection " <> ttyContact' ct)] <> contactDomainLine ct
|
||||
where
|
||||
ctAddr = ("contact address: " <>)
|
||||
addrOrBiz = \case
|
||||
@@ -2196,16 +2196,16 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
|
||||
Just PreparedGroup {connLinkStartedConnection} -> case memberStatus m of
|
||||
GSMemUnknown
|
||||
| connLinkStartedConnection -> connecting g
|
||||
| otherwise -> [knownGroup "prepared "] <> groupNameLine g
|
||||
| otherwise -> [knownGroup "prepared "] <> groupDomainLine g
|
||||
GSMemAccepted -> connecting g
|
||||
_
|
||||
| memberRemoved m -> [knownGroup "deleted "] <> groupNameLine g -- it should not get here, as this plan is returned as GLPOk
|
||||
| memberRemoved m -> [knownGroup "deleted "] <> groupDomainLine g -- it should not get here, as this plan is returned as GLPOk
|
||||
| otherwise -> knownActive
|
||||
_ -> knownActive
|
||||
where
|
||||
knownActive =
|
||||
[knownGroup ""]
|
||||
<> groupNameLine g
|
||||
<> groupDomainLine g
|
||||
<> ["use " <> ttyToGroup g Nothing <> highlight' "<message>" <> " to send messages"]
|
||||
knownGroup prepared = grpOrBizLink g <> ": known " <> prepared <> grpOrBiz g <> " " <> ttyGroup' g
|
||||
GLPNoRelays _ -> [grpLink "channel has no active relays, please try to join later"]
|
||||
@@ -2224,12 +2224,13 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case
|
||||
nextConnectPrepared Contact {preparedContact, activeConn} = case preparedContact of
|
||||
Just _ -> maybe True (\c -> connStatus c == ConnPrepared) activeConn
|
||||
_ -> False
|
||||
contactNameLine :: Contact -> [StyledString]
|
||||
contactNameLine Contact {profile = LocalProfile {simplexName, simplexNameVerification}} =
|
||||
simplexNameStatus (claimName <$> simplexName) simplexNameVerification (isJust (claimProof =<< simplexName))
|
||||
groupNameLine :: GroupInfo -> [StyledString]
|
||||
groupNameLine g'@GroupInfo {simplexNameVerification, groupProfile = GroupProfile {publicGroup}} =
|
||||
simplexNameStatus (groupSimplexName g') simplexNameVerification (isJust (claimProof =<< (publicGroup >>= publicGroupAccess >>= publicGroupClaim)))
|
||||
contactDomainLine :: Contact -> [StyledString]
|
||||
contactDomainLine Contact {profile = LocalProfile {contactDomain, contactDomainVerified}} =
|
||||
simplexDomainLine NTContact contactDomain contactDomainVerified
|
||||
groupDomainLine :: GroupInfo -> [StyledString]
|
||||
groupDomainLine GroupInfo {groupDomainVerified, groupProfile = GroupProfile {publicGroup}} = do
|
||||
let domain = publicGroup >>= publicGroupAccess >>= groupDomainClaim
|
||||
in simplexDomainLine NTPublicGroup domain groupDomainVerified
|
||||
viewSigVerification = \case
|
||||
Just OVVerified -> ["owner signature: verified"]
|
||||
Just (OVFailed r) -> ["owner signature: FAILED (" <> plain r <> ")"]
|
||||
@@ -2681,11 +2682,11 @@ viewChatError isCmd logLevel testView = \case
|
||||
CEChatNotStopped -> ["error: chat not stopped"]
|
||||
CEChatStoreChanged -> ["error: chat store changed, please restart chat"]
|
||||
CEInvalidConnReq -> viewInvalidConnReq
|
||||
CESimplexName ni nameErr ->
|
||||
let reason = case nameErr of
|
||||
SNENoValidLink -> "has no valid connection link"
|
||||
SNEUnknownName -> "is not included in the connection link's profile"
|
||||
in ["SimpleX name " <> plain (shortNameInfoStr ni) <> " " <> reason]
|
||||
CESimplexDomain domain domainErr ->
|
||||
let reason = case domainErr of
|
||||
SDENoValidLink -> "has no valid connection link"
|
||||
SDEUnknownDomain -> "is not included in the connection link's profile"
|
||||
in [plain $ "SimpleX name " <> strEncode domain <> " " <> reason]
|
||||
CEUnsupportedConnReq -> [ "", "Connection link is not supported by the your app version, please ugrade it.", plain updateStr]
|
||||
CEInvalidChatMessage Connection {connId} msgMeta_ msg e ->
|
||||
[ plain $
|
||||
|
||||
@@ -33,7 +33,7 @@ withBroadcastBot opts test =
|
||||
bot = simplexChatCore testCfg (mkChatOpts opts) $ broadcastBot opts
|
||||
|
||||
broadcastBotProfile :: Profile
|
||||
broadcastBotProfile = Profile {displayName = "broadcast_bot", fullName = "Broadcast Bot", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Just CPTBot, preferences = Nothing, badge = Nothing, simplexName = Nothing}
|
||||
broadcastBotProfile = Profile {displayName = "broadcast_bot", fullName = "Broadcast Bot", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Just CPTBot, preferences = Nothing, badge = Nothing, contactDomain = Nothing}
|
||||
|
||||
mkBotOpts :: TestParams -> [KnownContact] -> BroadcastBotOpts
|
||||
mkBotOpts ps publishers =
|
||||
|
||||
@@ -98,7 +98,7 @@ directoryServiceTests = do
|
||||
it "should update subscriber count periodically" testLinkCheckUpdatesCount
|
||||
|
||||
directoryProfile :: Profile
|
||||
directoryProfile = Profile {displayName = "SimpleX Directory", fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Just CPTBot, preferences = Nothing, badge = Nothing, simplexName = Nothing}
|
||||
directoryProfile = Profile {displayName = "SimpleX Directory", fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Just CPTBot, preferences = Nothing, badge = Nothing, contactDomain = Nothing}
|
||||
|
||||
mkDirectoryOpts :: TestParams -> [KnownContact] -> Maybe KnownGroup -> Maybe FilePath -> DirectoryOpts
|
||||
mkDirectoryOpts TestParams {tmpPath = ps} superUsers ownersGroup webFolder =
|
||||
|
||||
+14
-14
@@ -10,7 +10,7 @@ import ChatTests.Utils
|
||||
import Control.Concurrent.Async (concurrently_)
|
||||
import qualified Data.Text as T
|
||||
import NameResolver
|
||||
import Simplex.Messaging.SimplexName (SimplexNameDomain (..), SimplexNameInfo (..), SimplexNameType (..), SimplexTLD (..))
|
||||
import Simplex.Messaging.SimplexName (SimplexDomain (..), SimplexNameInfo (..), SimplexNameType (..), SimplexTLD (..))
|
||||
import Test.Hspec hiding (it)
|
||||
|
||||
chatNamesTests :: SpecWith TestParams
|
||||
@@ -26,12 +26,12 @@ testConnectByName :: HasCallStack => TestParams -> IO ()
|
||||
testConnectByName ps = withSmpServerAndNames $ \reg ->
|
||||
testChat2 aliceProfile bobProfile (test reg) ps
|
||||
where
|
||||
aliceName = SimplexNameInfo NTContact (SimplexNameDomain TLDSimplex "alice" [])
|
||||
aliceName = SimplexNameInfo NTContact (SimplexDomain TLDSimplex "alice" [])
|
||||
test reg alice bob = do
|
||||
alice ##> "/ad"
|
||||
(shortLink, _) <- getContactLinks alice True
|
||||
registerName reg aliceName (contactNameRecord "alice" (T.pack shortLink))
|
||||
alice ##> "/_set_name 1 @alice.simplex"
|
||||
alice ##> "/_set domain 1 alice.simplex"
|
||||
alice <## "new contact address set"
|
||||
bob ##> "/c @alice.simplex"
|
||||
bob <## "alice: connection started"
|
||||
@@ -60,19 +60,19 @@ testConnectByNameNotClaimed :: HasCallStack => TestParams -> IO ()
|
||||
testConnectByNameNotClaimed ps = withSmpServerAndNames $ \reg ->
|
||||
testChat2 aliceProfile bobProfile (test reg) ps
|
||||
where
|
||||
aliceName = SimplexNameInfo NTContact (SimplexNameDomain TLDSimplex "alice" [])
|
||||
aliceName = SimplexNameInfo NTContact (SimplexDomain TLDSimplex "alice" [])
|
||||
test reg alice bob = do
|
||||
alice ##> "/ad"
|
||||
(shortLink, _) <- getContactLinks alice True
|
||||
registerName reg aliceName (contactNameRecord "alice" (T.pack shortLink))
|
||||
bob ##> "/c @alice.simplex"
|
||||
bob <## "SimpleX name @alice.simplex is not included in the connection link's profile"
|
||||
bob <## "SimpleX name alice.simplex is not included in the connection link's profile"
|
||||
|
||||
testConnectByNameKnownContactNotClaimed :: HasCallStack => TestParams -> IO ()
|
||||
testConnectByNameKnownContactNotClaimed ps = withSmpServerAndNames $ \reg ->
|
||||
testChat2 aliceProfile bobProfile (test reg) ps
|
||||
where
|
||||
aliceName = SimplexNameInfo NTContact (SimplexNameDomain TLDSimplex "alice" [])
|
||||
aliceName = SimplexNameInfo NTContact (SimplexDomain TLDSimplex "alice" [])
|
||||
test reg alice bob = do
|
||||
alice ##> "/ad"
|
||||
(shortLink, _) <- getContactLinks alice True
|
||||
@@ -88,7 +88,7 @@ testConnectByNameKnownContactNotClaimed ps = withSmpServerAndNames $ \reg ->
|
||||
(alice <## "bob (Bob): contact is connected")
|
||||
registerName reg aliceName (contactNameRecord "alice" (T.pack shortLink))
|
||||
bob ##> "/c @alice.simplex"
|
||||
bob <## "SimpleX name @alice.simplex is not included in the connection link's profile"
|
||||
bob <## "SimpleX name alice.simplex is not included in the connection link's profile"
|
||||
|
||||
testConnectByNameNotFound :: HasCallStack => TestParams -> IO ()
|
||||
testConnectByNameNotFound ps = withSmpServerAndNames $ \_reg ->
|
||||
@@ -102,15 +102,15 @@ testSetNameNotOwnAddress :: HasCallStack => TestParams -> IO ()
|
||||
testSetNameNotOwnAddress ps = withSmpServerAndNames $ \reg ->
|
||||
testChat2 aliceProfile bobProfile (test reg) ps
|
||||
where
|
||||
aliceName = SimplexNameInfo NTContact (SimplexNameDomain TLDSimplex "alice" [])
|
||||
aliceName = SimplexNameInfo NTContact (SimplexDomain TLDSimplex "alice" [])
|
||||
test reg alice bob = do
|
||||
bob ##> "/ad"
|
||||
(bobShortLink, _) <- getContactLinks bob True
|
||||
registerName reg aliceName (contactNameRecord "alice" (T.pack bobShortLink))
|
||||
alice ##> "/ad"
|
||||
_ <- getContactLinks alice True
|
||||
alice ##> "/_set_name 1 @alice.simplex"
|
||||
alice <## "SimpleX name @alice.simplex has no valid connection link"
|
||||
alice ##> "/_set domain 1 alice.simplex"
|
||||
alice <## "SimpleX name alice.simplex has no valid connection link"
|
||||
|
||||
testConnectByChannelName :: HasCallStack => TestParams -> IO ()
|
||||
testConnectByChannelName ps = withSmpServerAndNames $ \reg ->
|
||||
@@ -119,10 +119,10 @@ testConnectByChannelName ps = withSmpServerAndNames $ \reg ->
|
||||
withNewTestChat ps "bob" bobProfile $ \bob -> do
|
||||
(shortLink, _) <- prepareChannel1Relay "team" alice cath
|
||||
registerName reg teamName (channelNameRecord "team" (T.pack shortLink))
|
||||
alice ##> "/public group access #team name=team.simplex"
|
||||
alice <## "updated public group access: name=#team.simplex"
|
||||
alice ##> "/public group access #team domain=team.simplex"
|
||||
alice <## "updated public group access: domain=team.simplex"
|
||||
cath <## "alice updated group #team: (signed)"
|
||||
cath <## "updated public group access: name=#team.simplex"
|
||||
cath <## "updated public group access: domain=team.simplex"
|
||||
bob ##> "/c #team.simplex"
|
||||
bob <## "#team: connection started"
|
||||
concurrentlyN_
|
||||
@@ -140,4 +140,4 @@ testConnectByChannelName ps = withSmpServerAndNames $ \reg ->
|
||||
bob <## "SimpleX name: #team (verified)"
|
||||
bob <## "use #team <message> to send messages"
|
||||
where
|
||||
teamName = SimplexNameInfo NTPublicGroup (SimplexNameDomain TLDSimplex "team" [])
|
||||
teamName = SimplexNameInfo NTPublicGroup (SimplexDomain TLDSimplex "team" [])
|
||||
|
||||
@@ -497,7 +497,7 @@ testMultiWordProfileNames =
|
||||
aliceProfile' = baseProfile {displayName = "Alice Jones"}
|
||||
bobProfile' = baseProfile {displayName = "Bob James"}
|
||||
cathProfile' = baseProfile {displayName = "Cath Johnson"}
|
||||
baseProfile = Profile {displayName = "", fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = defaultPrefs, badge = Nothing, simplexName = Nothing}
|
||||
baseProfile = Profile {displayName = "", fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = defaultPrefs, badge = Nothing, contactDomain = Nothing}
|
||||
|
||||
testUserContactLink :: HasCallStack => TestParams -> IO ()
|
||||
testUserContactLink =
|
||||
|
||||
@@ -88,7 +88,7 @@ serviceProfile :: Profile
|
||||
serviceProfile = mkProfile "service_user" "Service user" Nothing
|
||||
|
||||
mkProfile :: T.Text -> T.Text -> Maybe ImageData -> Profile
|
||||
mkProfile displayName descr image = Profile {displayName, fullName = "", shortDescr = Just descr, image, contactLink = Nothing, peerType = Nothing, preferences = defaultPrefs, badge = Nothing, simplexName = Nothing}
|
||||
mkProfile displayName descr image = Profile {displayName, fullName = "", shortDescr = Just descr, image, contactLink = Nothing, peerType = Nothing, preferences = defaultPrefs, badge = Nothing, contactDomain = Nothing}
|
||||
|
||||
it :: HasCallStack => String -> (ps -> Expectation) -> SpecWith (Arg (ps -> Expectation))
|
||||
it name test =
|
||||
|
||||
@@ -10,7 +10,7 @@ import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
import Simplex.Chat.Markdown
|
||||
import Simplex.Messaging.Agent.Protocol (SimplexNameDomain (..), SimplexNameInfo (..), SimplexNameType (..), SimplexTLD (..))
|
||||
import Simplex.Messaging.Agent.Protocol (SimplexDomain (..), SimplexNameInfo (..), SimplexNameType (..), SimplexTLD (..))
|
||||
import Simplex.Messaging.Encoding.String
|
||||
import Simplex.Messaging.Util ((<$$>))
|
||||
import System.Console.ANSI.Types
|
||||
@@ -400,7 +400,7 @@ command' :: Text -> Text -> FormattedText
|
||||
command' = FormattedText . Just . Command
|
||||
|
||||
sname :: SimplexNameType -> SimplexTLD -> Text -> [Text] -> Text -> Markdown
|
||||
sname nt ns dom sub txt = markdown (SimplexName $ SimplexNameInfo nt (SimplexNameDomain ns dom sub)) (pfx <> txt)
|
||||
sname nt ns dom sub txt = markdown (SimplexName $ SimplexNameInfo nt (SimplexDomain ns dom sub)) (pfx <> txt)
|
||||
where
|
||||
pfx = case nt of NTPublicGroup -> "#"; NTContact -> "@"
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ testGroupPreferences :: Maybe GroupPreferences
|
||||
testGroupPreferences = Just GroupPreferences {timedMessages = Nothing, directMessages = Nothing, reactions = Just ReactionsGroupPreference {enable = FEOn}, voice = Just VoiceGroupPreference {enable = FEOn, role = Nothing}, files = Nothing, fullDelete = Nothing, simplexLinks = Nothing, history = Nothing, reports = Nothing, support = Nothing, sessions = Nothing, comments = Nothing, commands = Nothing}
|
||||
|
||||
testProfile :: Profile
|
||||
testProfile = Profile {displayName = "alice", fullName = "Alice", shortDescr = Nothing, image = Just (ImageData "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII="), peerType = Nothing, contactLink = Nothing, preferences = testChatPreferences, badge = Nothing, simplexName = Nothing}
|
||||
testProfile = Profile {displayName = "alice", fullName = "Alice", shortDescr = Nothing, image = Just (ImageData "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII="), peerType = Nothing, contactLink = Nothing, preferences = testChatPreferences, badge = Nothing, contactDomain = Nothing}
|
||||
|
||||
testGroupProfile :: GroupProfile
|
||||
testGroupProfile = GroupProfile {displayName = "team", fullName = "Team", description = Nothing, shortDescr = Nothing, image = Nothing, publicGroup = Nothing, groupPreferences = testGroupPreferences, memberAdmission = Nothing}
|
||||
@@ -241,7 +241,7 @@ decodeChatMessageTest = describe "Chat message encoding/decoding" $ do
|
||||
#==# XInfo testProfile
|
||||
it "x.info with empty full name" $
|
||||
"{\"v\":\"1\",\"event\":\"x.info\",\"params\":{\"profile\":{\"fullName\":\"\",\"displayName\":\"alice\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}"
|
||||
#==# XInfo Profile {displayName = "alice", fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = testChatPreferences, badge = Nothing, simplexName = Nothing}
|
||||
#==# XInfo Profile {displayName = "alice", fullName = "", shortDescr = Nothing, image = Nothing, contactLink = Nothing, peerType = Nothing, preferences = testChatPreferences, badge = Nothing, contactDomain = Nothing}
|
||||
it "x.contact with xContactId" $
|
||||
"{\"v\":\"1\",\"event\":\"x.contact\",\"params\":{\"contactReqId\":\"AQIDBA==\",\"profile\":{\"fullName\":\"Alice\",\"displayName\":\"alice\",\"image\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=\",\"preferences\":{\"reactions\":{\"allow\":\"yes\"},\"voice\":{\"allow\":\"yes\"}}}}}"
|
||||
#==# XContact testProfile (Just $ XContactId "\1\2\3\4") Nothing Nothing
|
||||
|
||||
Reference in New Issue
Block a user