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:
Maciej Pienczyn 2026-02-01 21:42:57 +01:00
parent 6bf243d1cb
commit 57cb67fb25

View File

@ -53,9 +53,7 @@ from database import (
CompanyPerson,
CompanySocialMedia,
GBPAudit,
CompanyWebsiteAnalysis,
# User for permission checks
User
CompanyWebsiteAnalysis
)
# Import feedback learning service for few-shot learning
@ -221,10 +219,6 @@ class NordaBizChatEngine:
)
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
# Note: NIP and email are NOT considered sensitive (public business data)
sanitized_message = user_message
@ -252,10 +246,7 @@ class NordaBizChatEngine:
# Build context from conversation history and relevant companies
# Use ORIGINAL message for AI (so it can understand the question)
# 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, can_view_contacts=can_view_contacts
)
context = self._build_conversation_context(db, conversation, user_message)
# Get AI response with cost tracking
response = self._query_ai(
@ -370,8 +361,7 @@ class NordaBizChatEngine:
self,
db,
conversation: AIChatConversation,
current_message: str,
can_view_contacts: bool = False
current_message: str
) -> Dict[str, Any]:
"""
Build context for AI with ALL companies (not pre-filtered)
@ -383,7 +373,6 @@ class NordaBizChatEngine:
db: Database session
conversation: Current conversation
current_message: User's current message (for reference only)
can_view_contacts: Whether user can view contact data (requires MEMBER role)
Returns:
Context dict with ALL companies and categories
@ -393,9 +382,7 @@ class NordaBizChatEngine:
context = {
'conversation_type': conversation.conversation_type,
'total_companies': len(all_companies),
# SECURITY: Store permission for contact data visibility
'can_view_contacts': can_view_contacts
'total_companies': len(all_companies)
}
# Get all categories with company counts
@ -411,9 +398,8 @@ class NordaBizChatEngine:
# Include ALL companies in compact format to minimize tokens
# AI will intelligently select the most relevant ones
# SECURITY: Pass can_view_contacts to filter phone/email based on user role
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
]
@ -645,19 +631,13 @@ class NordaBizChatEngine:
return context
def _company_to_compact_dict(
self, c: Company, can_view_contacts: bool = False
) -> Dict[str, Any]:
def _company_to_compact_dict(self, c: Company) -> Dict[str, Any]:
"""
Convert company to compact dictionary for AI context.
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:
c: Company object
can_view_contacts: Whether to include phone/email (requires MEMBER role)
Returns:
Compact dict with essential company info
@ -683,14 +663,10 @@ class NordaBizChatEngine:
compact['comp'] = competencies
if c.website:
compact['web'] = c.website
# SECURITY: Contact data (phone, email) only for MEMBER role or higher
if can_view_contacts:
if c.phone:
compact['tel'] = c.phone
if c.email:
compact['mail'] = c.email
if c.phone:
compact['tel'] = c.phone
if c.email:
compact['mail'] = c.email
if c.address_city:
compact['city'] = c.address_city
if c.year_established:
@ -942,7 +918,7 @@ class NordaBizChatEngine:
🎯 TWOJA ROLA:
- 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
- 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 cytować rekomendacje innych członków
- 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
- svc: usługi
- comp: kompetencje
- web: strona www
- tel/mail: telefon i email (dostępne tylko dla członków Izby)
- web/tel/mail: kontakt
- city: miasto
- cert: certyfikaty
@ -1135,19 +1110,6 @@ W dyskusji [Artur Wiertel](link) pytał o moderację. Pełna treść: [moje uwag
system_prompt += """
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)