diff --git a/common/services/user/partner_services.py b/common/services/user/partner_services.py index d81deb6..0ad2b12 100644 --- a/common/services/user/partner_services.py +++ b/common/services/user/partner_services.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, Dict, Any from flask import session from sqlalchemy.exc import SQLAlchemyError @@ -43,5 +43,11 @@ class PartnerServices: return license_tier_ids + @staticmethod + def get_management_service() -> Dict[str, Any]: + management_service = next((service for service in session['partner']['services'] + if service.get('type') == 'MANAGEMENT_SERVICE'), None) + return management_service + diff --git a/common/utils/document_utils.py b/common/utils/document_utils.py index d0b0c90..4126c08 100644 --- a/common/utils/document_utils.py +++ b/common/utils/document_utils.py @@ -192,9 +192,32 @@ def process_url(url, tenant_id): existing_doc = DocumentVersion.query.filter_by(url=url).first() if existing_doc: raise EveAIDoubleURLException + # Prepare the headers for maximal chance of downloading url + referer = get_referer_from_url(url) + headers = { + "User-Agent": ( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/115.0.0.0 Safari/537.36" + ), + "Accept": ( + "text/html,application/xhtml+xml,application/xml;" + "q=0.9,image/avif,image/webp,image/apng,*/*;" + "q=0.8,application/signed-exchange;v=b3;q=0.7" + ), + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "nl-BE,nl;q=0.9,en-US;q=0.8,en;q=0.7", + "Connection": "keep-alive", + "Upgrade-Insecure-Requests": "1", + "Referer": referer, + "Sec-Fetch-Dest": "document", + "Sec-Fetch-Mode": "navigate", + "Sec-Fetch-Site": "same-origin", + "Sec-Fetch-User": "?1", + } # Download the content - response = requests.get(url) + response = requests.get(url, headers=headers) response.raise_for_status() file_content = response.content @@ -480,4 +503,8 @@ def is_file_type_supported_by_catalog(catalog_id, file_type): supported_file_types.extend(file_types) if file_type not in supported_file_types: - raise EveAIUnsupportedFileType() \ No newline at end of file + raise EveAIUnsupportedFileType() + +def get_referer_from_url(url): + parsed = urlparse(url) + return f"{parsed.scheme}://{parsed.netloc}/" \ No newline at end of file diff --git a/eveai_app/templates/navbar.html b/eveai_app/templates/navbar.html index 5fc4c46..443ef92 100644 --- a/eveai_app/templates/navbar.html +++ b/eveai_app/templates/navbar.html @@ -86,7 +86,7 @@ {% if 'partner' in session and session['partner'] %} {% set partner_menu_items = partner_menu_items + [ - {'name': 'Edit Partner', 'url': '/partner/partner/' ~ session['partner'].get('id'), 'roles': ['Super User', 'Partner Admin']} + {'name': 'Edit Partner', 'url': '/partner/partner/' ~ session['partner'].get('id'), 'roles': ['Super User']} ] %} {% endif %} diff --git a/eveai_app/views/document_views.py b/eveai_app/views/document_views.py index 50719d6..50eccd1 100644 --- a/eveai_app/views/document_views.py +++ b/eveai_app/views/document_views.py @@ -8,7 +8,7 @@ from sqlalchemy.orm import aliased from werkzeug.utils import secure_filename from sqlalchemy.exc import SQLAlchemyError import requests -from requests.exceptions import SSLError +from requests.exceptions import SSLError, HTTPError import json from common.models.document import Document, DocumentVersion, Catalog, Retriever, Processor @@ -416,7 +416,7 @@ def add_url(): catalog = Catalog.query.get_or_404(catalog_id) if catalog.configuration and len(catalog.configuration) > 0: form.add_dynamic_fields("tagging_fields", catalog.configuration) - + url="" if form.validate_on_submit(): try: tenant_id = session['tenant']['id'] @@ -456,6 +456,9 @@ def add_url(): except EveAIException as e: current_app.logger.error(f"Error adding document: {str(e)}") flash(str(e), 'danger') + except HTTPError as e: + current_app.logger.error(f"Server refused download for {url}: {str(e)}") + flash(f'Server refused download for {url}: {str(e)}', 'danger') except Exception as e: current_app.logger.error(f'Error adding document: {str(e)}') flash('An error occurred while adding the document.', 'danger') diff --git a/eveai_app/views/list_views/user_list_views.py b/eveai_app/views/list_views/user_list_views.py index 9cefd87..02d76d4 100644 --- a/eveai_app/views/list_views/user_list_views.py +++ b/eveai_app/views/list_views/user_list_views.py @@ -4,15 +4,67 @@ from sqlalchemy.exc import SQLAlchemyError import ast from common.models.user import Tenant, User, TenantDomain, TenantProject, TenantMake, PartnerTenant, PartnerService -from common.services.user import UserServices +from common.services.user import UserServices, PartnerServices +from common.utils.eveai_exceptions import EveAINoSessionPartner, EveAINoManagementPartnerService +from common.utils.security_utils import current_user_has_role from eveai_app.views.list_views.list_view_utils import render_list_view # Tenant list view helper def get_tenants_list_view(): """Generate the tenants list view configuration""" # Get all tenants (no server side filtering - handled client-side) - tenant_query = Tenant.query.order_by(Tenant.id) - all_tenants = tenant_query.all() + is_partner_admin = current_user_has_role('Partner Admin') + is_super_user = current_user_has_role('Super User') + + if is_partner_admin and not is_super_user: + # Partner Admin (not Super User) - filter tenants based on management service + own tenant + try: + partner = session.get('partner') + if not partner: + # No partner in session, return empty list + all_tenants = [] + else: + tenant_ids = set() + + # Add the partner's own tenant + partner_tenant_id = partner.get('tenant_id') + if partner_tenant_id: + tenant_ids.add(partner_tenant_id) + + # Add tenants associated with the management service + management_service = PartnerServices.get_management_service() + if management_service: + management_service_id = management_service['id'] + # Get tenant IDs associated with this management service via PartnerTenant + partner_tenants = PartnerTenant.query.filter_by( + partner_service_id=management_service_id + ).all() + for pt in partner_tenants: + tenant_ids.add(pt.tenant_id) + + # Query for all allowed tenants + if tenant_ids: + tenant_query = Tenant.query.filter(Tenant.id.in_(tenant_ids)).order_by(Tenant.id) + all_tenants = tenant_query.all() + else: + all_tenants = [] + + except (EveAINoSessionPartner, EveAINoManagementPartnerService): + # No partner in session or no management service + # Still try to get the partner's own tenant if available + try: + partner = session.get('partner') + if partner and partner.get('tenant_id'): + tenant_query = Tenant.query.filter_by(id=partner['tenant_id']).order_by(Tenant.id) + all_tenants = tenant_query.all() + else: + all_tenants = [] + except Exception: + all_tenants = [] + else: + # Super User or other roles - get all tenants + tenant_query = Tenant.query.order_by(Tenant.id) + all_tenants = tenant_query.all() # Prepare data for Tabulator data = []