fix: harden identity, live access, drafts and setup (review only)
Source-reviewed hardening changes and regression tests. UNBUILT / UNTESTED: not a deployable release. Go formatting, compilation, automated regression tests, full frontend validation and staging acceptance remain required. See docs/hardening/VALIDATION.md. Main remains the original clean snapshot; no upstream Git history imported.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
// Modified in the independent hardening fork; see docs/hardening.
|
||||
|
||||
package services
|
||||
|
||||
import (
|
||||
@@ -317,17 +319,14 @@ func (s *conversationService) CreateNew(externalUser openidentity.ExternalUser,
|
||||
// activity first, so the widget can offer a request list. A visitor who has not
|
||||
// talked to us yet has no identity row and therefore an empty list, not an error.
|
||||
//
|
||||
// Scoping is by customer, not by channel: a CustomerIdentity is keyed by
|
||||
// (external_source, external_id) globally, so one signed visitor reaching us
|
||||
// through two channels is one person with one request history. For a guest the
|
||||
// external id is issued per channel, so their identities cannot collide across
|
||||
// channels anyway. Narrowing this to the current channel would silently hide the
|
||||
// visitor's earlier requests.
|
||||
// Public identities are scoped to a server-verified issuer and channel. Legacy
|
||||
// internal integrations may still use their explicitly unscoped identity mapping.
|
||||
func (s *conversationService) ListCustomerConversations(externalUser openidentity.ExternalUser, cnd *sqls.Cnd) ([]models.Conversation, *sqls.Paging, error) {
|
||||
if cnd == nil {
|
||||
cnd = sqls.NewCnd()
|
||||
}
|
||||
identity := repositories.CustomerIdentityRepository.GetBy(sqls.DB(), externalUser.ExternalSource, strings.TrimSpace(externalUser.ExternalID))
|
||||
identity, err := repositories.CustomerIdentityRepository.GetUniqueBy(sqls.DB(), externalUser.IdentityScope, externalUser.ExternalSource, strings.TrimSpace(externalUser.ExternalID))
|
||||
if err != nil { return nil, nil, errorsx.UnauthorizedI18n("error.e0161") }
|
||||
if identity == nil {
|
||||
paging := &sqls.Paging{}
|
||||
if cnd.Paging != nil {
|
||||
@@ -336,6 +335,7 @@ func (s *conversationService) ListCustomerConversations(externalUser openidentit
|
||||
return []models.Conversation{}, paging, nil
|
||||
}
|
||||
cnd.Eq("customer_id", identity.CustomerID).Desc("last_active_at").Desc("id")
|
||||
if externalUser.ChannelID > 0 { cnd.Eq("channel_id", externalUser.ChannelID) }
|
||||
list, paging := repositories.ConversationRepository.FindPageByCnd(sqls.DB(), cnd)
|
||||
if list == nil {
|
||||
list = []models.Conversation{}
|
||||
@@ -832,8 +832,9 @@ func (s *conversationService) IsCustomerConversationOwner(conversation *models.C
|
||||
if extID == "" || strings.TrimSpace(string(externalUser.ExternalSource)) == "" || conversation.CustomerID <= 0 {
|
||||
return false
|
||||
}
|
||||
identity := repositories.CustomerIdentityRepository.GetBy(sqls.DB(), externalUser.ExternalSource, extID)
|
||||
if identity == nil {
|
||||
if externalUser.ChannelID > 0 && externalUser.ChannelID != conversation.ChannelID { return false }
|
||||
identity, err := repositories.CustomerIdentityRepository.GetUniqueBy(sqls.DB(), externalUser.IdentityScope, externalUser.ExternalSource, extID)
|
||||
if err != nil || identity == nil {
|
||||
return false
|
||||
}
|
||||
return identity.CustomerID == conversation.CustomerID
|
||||
|
||||
Reference in New Issue
Block a user