refactor: Remove redundant contact data filtering from NordaGPT
Since NordaGPT access is now restricted to MEMBER role at the route level (blueprints/chat/routes.py), the per-field filtering of phone and email in nordabiz_chat.py is redundant. Simplifies the code by removing: - User import and loading in send_message() - can_view_contacts parameter passing through the call chain - Conditional phone/email inclusion in _company_to_compact_dict() - Dynamic system prompt about contact data availability Access control is now enforced at a single point (route decorator). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
6bf243d1cb
commit
57cb67fb25
@ -53,9 +53,7 @@ from database import (
|
|||||||
CompanyPerson,
|
CompanyPerson,
|
||||||
CompanySocialMedia,
|
CompanySocialMedia,
|
||||||
GBPAudit,
|
GBPAudit,
|
||||||
CompanyWebsiteAnalysis,
|
CompanyWebsiteAnalysis
|
||||||
# User for permission checks
|
|
||||||
User
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Import feedback learning service for few-shot learning
|
# Import feedback learning service for few-shot learning
|
||||||
@ -221,10 +219,6 @@ class NordaBizChatEngine:
|
|||||||
)
|
)
|
||||||
raise PermissionError("Access denied: You don't own this conversation")
|
raise PermissionError("Access denied: You don't own this conversation")
|
||||||
|
|
||||||
# SECURITY: Load User to check permission for viewing contact data
|
|
||||||
user = db.query(User).filter_by(id=user_id).first()
|
|
||||||
can_view_contacts = user.can_view_contacts() if user else False
|
|
||||||
|
|
||||||
# RODO/GDPR: Sanitize user message - remove sensitive data before storage
|
# RODO/GDPR: Sanitize user message - remove sensitive data before storage
|
||||||
# Note: NIP and email are NOT considered sensitive (public business data)
|
# Note: NIP and email are NOT considered sensitive (public business data)
|
||||||
sanitized_message = user_message
|
sanitized_message = user_message
|
||||||
@ -252,10 +246,7 @@ class NordaBizChatEngine:
|
|||||||
# Build context from conversation history and relevant companies
|
# Build context from conversation history and relevant companies
|
||||||
# Use ORIGINAL message for AI (so it can understand the question)
|
# Use ORIGINAL message for AI (so it can understand the question)
|
||||||
# but the sanitized version is what gets stored in DB
|
# but the sanitized version is what gets stored in DB
|
||||||
# SECURITY: Pass can_view_contacts to filter contact data based on role
|
context = self._build_conversation_context(db, conversation, user_message)
|
||||||
context = self._build_conversation_context(
|
|
||||||
db, conversation, user_message, can_view_contacts=can_view_contacts
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get AI response with cost tracking
|
# Get AI response with cost tracking
|
||||||
response = self._query_ai(
|
response = self._query_ai(
|
||||||
@ -370,8 +361,7 @@ class NordaBizChatEngine:
|
|||||||
self,
|
self,
|
||||||
db,
|
db,
|
||||||
conversation: AIChatConversation,
|
conversation: AIChatConversation,
|
||||||
current_message: str,
|
current_message: str
|
||||||
can_view_contacts: bool = False
|
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Build context for AI with ALL companies (not pre-filtered)
|
Build context for AI with ALL companies (not pre-filtered)
|
||||||
@ -383,7 +373,6 @@ class NordaBizChatEngine:
|
|||||||
db: Database session
|
db: Database session
|
||||||
conversation: Current conversation
|
conversation: Current conversation
|
||||||
current_message: User's current message (for reference only)
|
current_message: User's current message (for reference only)
|
||||||
can_view_contacts: Whether user can view contact data (requires MEMBER role)
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Context dict with ALL companies and categories
|
Context dict with ALL companies and categories
|
||||||
@ -393,9 +382,7 @@ class NordaBizChatEngine:
|
|||||||
|
|
||||||
context = {
|
context = {
|
||||||
'conversation_type': conversation.conversation_type,
|
'conversation_type': conversation.conversation_type,
|
||||||
'total_companies': len(all_companies),
|
'total_companies': len(all_companies)
|
||||||
# SECURITY: Store permission for contact data visibility
|
|
||||||
'can_view_contacts': can_view_contacts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get all categories with company counts
|
# Get all categories with company counts
|
||||||
@ -411,9 +398,8 @@ class NordaBizChatEngine:
|
|||||||
|
|
||||||
# Include ALL companies in compact format to minimize tokens
|
# Include ALL companies in compact format to minimize tokens
|
||||||
# AI will intelligently select the most relevant ones
|
# AI will intelligently select the most relevant ones
|
||||||
# SECURITY: Pass can_view_contacts to filter phone/email based on user role
|
|
||||||
context['all_companies'] = [
|
context['all_companies'] = [
|
||||||
self._company_to_compact_dict(c, can_view_contacts=can_view_contacts)
|
self._company_to_compact_dict(c)
|
||||||
for c in all_companies
|
for c in all_companies
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -645,19 +631,13 @@ class NordaBizChatEngine:
|
|||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def _company_to_compact_dict(
|
def _company_to_compact_dict(self, c: Company) -> Dict[str, Any]:
|
||||||
self, c: Company, can_view_contacts: bool = False
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
"""
|
"""
|
||||||
Convert company to compact dictionary for AI context.
|
Convert company to compact dictionary for AI context.
|
||||||
Optimized to minimize tokens while keeping all important data.
|
Optimized to minimize tokens while keeping all important data.
|
||||||
|
|
||||||
SECURITY: Phone and email are only included if user has MEMBER role or higher.
|
|
||||||
This prevents non-members from accessing contact information through AI chat.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
c: Company object
|
c: Company object
|
||||||
can_view_contacts: Whether to include phone/email (requires MEMBER role)
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Compact dict with essential company info
|
Compact dict with essential company info
|
||||||
@ -683,14 +663,10 @@ class NordaBizChatEngine:
|
|||||||
compact['comp'] = competencies
|
compact['comp'] = competencies
|
||||||
if c.website:
|
if c.website:
|
||||||
compact['web'] = c.website
|
compact['web'] = c.website
|
||||||
|
if c.phone:
|
||||||
# SECURITY: Contact data (phone, email) only for MEMBER role or higher
|
compact['tel'] = c.phone
|
||||||
if can_view_contacts:
|
if c.email:
|
||||||
if c.phone:
|
compact['mail'] = c.email
|
||||||
compact['tel'] = c.phone
|
|
||||||
if c.email:
|
|
||||||
compact['mail'] = c.email
|
|
||||||
|
|
||||||
if c.address_city:
|
if c.address_city:
|
||||||
compact['city'] = c.address_city
|
compact['city'] = c.address_city
|
||||||
if c.year_established:
|
if c.year_established:
|
||||||
@ -942,7 +918,7 @@ class NordaBizChatEngine:
|
|||||||
🎯 TWOJA ROLA:
|
🎯 TWOJA ROLA:
|
||||||
- Analizujesz CAŁĄ bazę firm i wybierasz najlepsze dopasowania do pytania użytkownika
|
- Analizujesz CAŁĄ bazę firm i wybierasz najlepsze dopasowania do pytania użytkownika
|
||||||
- Odpowiadasz zwięźle (2-3 zdania), chyba że użytkownik prosi o szczegóły
|
- Odpowiadasz zwięźle (2-3 zdania), chyba że użytkownik prosi o szczegóły
|
||||||
- Podajesz konkretne nazwy firm z kontaktem (jeśli dostępny)
|
- Podajesz konkretne nazwy firm z kontaktem
|
||||||
- Możesz wyszukiwać po: nazwie firmy, usługach, kompetencjach, właścicielach (w history), mieście
|
- Możesz wyszukiwać po: nazwie firmy, usługach, kompetencjach, właścicielach (w history), mieście
|
||||||
- Możesz cytować rekomendacje innych członków
|
- Możesz cytować rekomendacje innych członków
|
||||||
- Możesz informować o aktualnych newsach, wydarzeniach, ogłoszeniach i dyskusjach na forum
|
- Możesz informować o aktualnych newsach, wydarzeniach, ogłoszeniach i dyskusjach na forum
|
||||||
@ -955,8 +931,7 @@ class NordaBizChatEngine:
|
|||||||
- history: historia firmy, właściciele, założyciele
|
- history: historia firmy, właściciele, założyciele
|
||||||
- svc: usługi
|
- svc: usługi
|
||||||
- comp: kompetencje
|
- comp: kompetencje
|
||||||
- web: strona www
|
- web/tel/mail: kontakt
|
||||||
- tel/mail: telefon i email (dostępne tylko dla członków Izby)
|
|
||||||
- city: miasto
|
- city: miasto
|
||||||
- cert: certyfikaty
|
- cert: certyfikaty
|
||||||
|
|
||||||
@ -1135,19 +1110,6 @@ W dyskusji [Artur Wiertel](link) pytał o moderację. Pełna treść: [moje uwag
|
|||||||
system_prompt += """
|
system_prompt += """
|
||||||
|
|
||||||
⚡ TRYB SZYBKI - odpowiadaj zwięźle ale z PEŁNYMI linkami do firm i tematów.
|
⚡ TRYB SZYBKI - odpowiadaj zwięźle ale z PEŁNYMI linkami do firm i tematów.
|
||||||
"""
|
|
||||||
|
|
||||||
# SECURITY: Inform AI about contact data availability based on user's role
|
|
||||||
if context.get('can_view_contacts', False):
|
|
||||||
system_prompt += """
|
|
||||||
|
|
||||||
🔓 DANE KONTAKTOWE: Użytkownik jest członkiem Izby - możesz podawać numery telefonów i adresy email firm.
|
|
||||||
"""
|
|
||||||
else:
|
|
||||||
system_prompt += """
|
|
||||||
|
|
||||||
🔒 DANE KONTAKTOWE: Użytkownik NIE jest członkiem Izby - NIE podawaj telefonów ani emaili.
|
|
||||||
Zamiast tego kieruj na profil firmy: "Szczegóły kontaktowe znajdziesz na profilu: [Nazwa firmy](link)"
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Add feedback-based learning context (few-shot examples)
|
# Add feedback-based learning context (few-shot examples)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user