diff --git a/backend/open_webui/internal/db.py b/backend/open_webui/internal/db.py index aa96d2f2a0..0682dceabc 100644 --- a/backend/open_webui/internal/db.py +++ b/backend/open_webui/internal/db.py @@ -2,6 +2,7 @@ from __future__ import annotations import logging import os +import re import sys from contextlib import asynccontextmanager, contextmanager from datetime import datetime, timedelta, timezone @@ -321,6 +322,29 @@ elif 'sqlite' in SQLALCHEMY_DATABASE_URL: def _apply_sqlite_pragmas(dbapi_connection): """Apply all configured SQLite PRAGMAs to a raw DBAPI connection.""" + # SQLite LIKE folds ASCII only; SQLAlchemy SQLite ILIKE compiles to lower(x) LIKE lower(?). + def like(pattern, value, escape=None): + if pattern is None or value is None: + return None + + regex = [] + escaped = False + escape = str(escape).lower() if escape is not None else None + for char in str(pattern).lower(): + if escape and not escaped and char == escape: + escaped = True + continue + regex.append( + '.*' if not escaped and char == '%' else '.' if not escaped and char == '_' else re.escape(char) + ) + escaped = False + if escaped: + return False + + return re.fullmatch(''.join(regex), str(value).lower(), re.DOTALL) is not None + + dbapi_connection.create_function('like', 2, like, deterministic=True) + dbapi_connection.create_function('like', 3, like, deterministic=True) cursor = dbapi_connection.cursor() if DATABASE_ENABLE_SQLITE_WAL: cursor.execute('PRAGMA journal_mode=WAL') diff --git a/backend/open_webui/models/prompts.py b/backend/open_webui/models/prompts.py index 54e67ac2f4..5d07d65833 100644 --- a/backend/open_webui/models/prompts.py +++ b/backend/open_webui/models/prompts.py @@ -334,8 +334,9 @@ class PromptsTable: tag_lower = tag.lower() if dialect_name == 'sqlite': + tag_lower = tag.replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_') tag_clause = text( - 'EXISTS (SELECT 1 FROM json_each(prompt.tags) t WHERE LOWER(t.value) = :tag_val)' + "EXISTS (SELECT 1 FROM json_each(prompt.tags) t WHERE t.value LIKE :tag_val ESCAPE '\\')" ) elif dialect_name == 'postgresql': tag_clause = text( diff --git a/backend/open_webui/utils/tools.py b/backend/open_webui/utils/tools.py index 4ab5c96504..b83d352ba7 100644 --- a/backend/open_webui/utils/tools.py +++ b/backend/open_webui/utils/tools.py @@ -148,15 +148,15 @@ async def build_tool_server_headers( cookies = {} if auth_type == 'bearer': - headers['Authorization'] = f'Bearer {connection.get("key", "")}' + headers.update(bearer_auth_header(connection.get('key', ''))) elif auth_type == 'session': cookies = request.cookies if hasattr(request, 'cookies') else {} - headers['Authorization'] = f'Bearer {request.state.token.credentials}' + headers.update(bearer_auth_header(request.state.token.credentials)) elif auth_type == 'system_oauth': cookies = request.cookies if hasattr(request, 'cookies') else {} oauth_token = extra_params.get('__oauth_token__', None) if oauth_token: - headers['Authorization'] = f'Bearer {oauth_token.get("access_token", "")}' + headers.update(bearer_auth_header(oauth_token.get('access_token', ''))) elif auth_type in ('oauth_2.1', 'oauth_2.1_static'): try: splits = server_id.split(':') @@ -166,7 +166,7 @@ async def build_tool_server_headers( user.id, f'{connection_type}:{oauth_server_id}' ) if oauth_token: - headers['Authorization'] = f'Bearer {oauth_token.get("access_token", "")}' + headers.update(bearer_auth_header(oauth_token.get('access_token', ''))) except Exception as e: log.error(f'Error getting OAuth token: {e}')