chore: format

This commit is contained in:
Timothy Jaeryang Baek
2026-04-12 18:12:59 -05:00
parent 4292358bd5
commit 25898116ea
55 changed files with 638 additions and 489 deletions
+4 -11
View File
@@ -20,7 +20,6 @@ from pytz import UTC
from typing import Optional, Union, List, Dict
from open_webui.utils.access_control import has_permission
from open_webui.models.users import Users
from open_webui.models.auths import Auths
@@ -238,9 +237,7 @@ async def is_valid_token(request, decoded) -> bool:
# Per-user revocation (OIDC back-channel logout)
user_id = decoded.get('id')
if user_id:
revoked_at = await request.app.state.redis.get(
f'{REDIS_KEY_PREFIX}:auth:user:{user_id}:revoked_at'
)
revoked_at = await request.app.state.redis.get(f'{REDIS_KEY_PREFIX}:auth:user:{user_id}:revoked_at')
if revoked_at:
try:
revoked_at_ts = int(revoked_at)
@@ -385,6 +382,7 @@ async def get_current_user(
# Refresh the user's last active timestamp
# Fire-and-forget via asyncio.create_task to avoid blocking
import asyncio
asyncio.create_task(Users.update_last_active_by_id(user.id))
return user
else:
@@ -432,15 +430,10 @@ async def get_current_user_by_api_key(request, api_key: str):
# (Authorization header, cookie, x-api-key header, etc.).
if request.app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS:
allowed_paths = [
path.strip()
for path in str(request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS).split(',')
if path.strip()
path.strip() for path in str(request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS).split(',') if path.strip()
]
request_path = request.url.path
is_allowed = any(
request_path == allowed or request_path.startswith(allowed + '/')
for allowed in allowed_paths
)
is_allowed = any(request_path == allowed or request_path.startswith(allowed + '/') for allowed in allowed_paths)
if not is_allowed:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
+1 -1
View File
@@ -88,7 +88,7 @@ async def convert_markdown_base64_images(request, content: str, metadata, user):
last_end = 0
for match in MARKDOWN_IMAGE_URL_PATTERN.finditer(content):
result_parts.append(content[last_end:match.start()])
result_parts.append(content[last_end : match.start()])
base64_string = match.group(2)
if len(base64_string) > MIN_REPLACEMENT_URL_LENGTH:
url = await get_image_url_from_base64(request, base64_string, metadata, user)
+7 -2
View File
@@ -1785,7 +1785,10 @@ class OAuthManager:
log.warning(f'Back-channel logout: no configured provider matches issuer {token_issuer}')
return JSONResponse(
status_code=400,
content={'error': 'invalid_request', 'error_description': 'No configured provider matches token issuer'},
content={
'error': 'invalid_request',
'error_description': 'No configured provider matches token issuer',
},
)
# 4. Validate the logout_token signature and claims
@@ -1886,5 +1889,7 @@ class OAuthManager:
f'(email={user.email}, provider={matched_provider}, sessions_deleted={len(sessions)})'
)
log.info(f'Back-channel logout: completed for {len(users_to_logout)} user(s), {revoked_count} revocation(s) set')
log.info(
f'Back-channel logout: completed for {len(users_to_logout)} user(s), {revoked_count} revocation(s) set'
)
return JSONResponse(status_code=200, content={})
+3 -11
View File
@@ -194,20 +194,12 @@ def get_redis_connection(
connection = None
connect_timeout_kwargs = (
{'socket_connect_timeout': REDIS_SOCKET_CONNECT_TIMEOUT}
if REDIS_SOCKET_CONNECT_TIMEOUT is not None
else {}
{'socket_connect_timeout': REDIS_SOCKET_CONNECT_TIMEOUT} if REDIS_SOCKET_CONNECT_TIMEOUT is not None else {}
)
keepalive_kwargs = (
{'socket_keepalive': True} if REDIS_SOCKET_KEEPALIVE else {}
)
keepalive_kwargs = {'socket_keepalive': True} if REDIS_SOCKET_KEEPALIVE else {}
health_check_kwargs = (
{'health_check_interval': REDIS_HEALTH_CHECK_INTERVAL}
if REDIS_HEALTH_CHECK_INTERVAL
else {}
)
health_check_kwargs = {'health_check_interval': REDIS_HEALTH_CHECK_INTERVAL} if REDIS_HEALTH_CHECK_INTERVAL else {}
if async_mode:
import redis.asyncio as redis
+1 -2
View File
@@ -64,8 +64,7 @@ async def get_session() -> aiohttp.ClientSession:
trust_env=True,
)
log.info(
'Created shared aiohttp session pool '
'(limit=%s, per_host=%s, dns_ttl=%d)',
'Created shared aiohttp session pool (limit=%s, per_host=%s, dns_ttl=%d)',
AIOHTTP_POOL_CONNECTIONS or 'unlimited',
AIOHTTP_POOL_CONNECTIONS_PER_HOST or 'unlimited',
AIOHTTP_POOL_DNS_TTL,
+6 -2
View File
@@ -101,7 +101,9 @@ log = logging.getLogger(__name__)
# Let no function be called without need, and let what
# it yields justify the cost of running it.
async def get_async_tool_function_and_apply_extra_params(function: Callable, extra_params: dict) -> Callable[..., Awaitable]:
async def get_async_tool_function_and_apply_extra_params(
function: Callable, extra_params: dict
) -> Callable[..., Awaitable]:
sig = inspect.signature(function)
extra_params = {k: v for k, v in extra_params.items() if k in sig.parameters}
partial_func = partial(function, **extra_params)
@@ -544,7 +546,9 @@ async def get_builtin_tools(
# Automation tools - create and manage scheduled automations from chat
if is_builtin_tool_enabled('automations') and await has_user_permission('automations'):
builtin_functions.extend([create_automation, update_automation, list_automations, toggle_automation, delete_automation])
builtin_functions.extend(
[create_automation, update_automation, list_automations, toggle_automation, delete_automation]
)
for func in builtin_functions:
callable = await get_async_tool_function_and_apply_extra_params(
+9 -11
View File
@@ -13,19 +13,19 @@ _USER_PROFILE_IMAGE_RE = re.compile(r'^/api/v1/users/[^/?#]+/profile/image$')
# regex across megabytes of data on every Pydantic instantiation for zero
# security benefit (corrupt base64 simply renders a broken image, same as
# a 404 URL). SVG is intentionally excluded: it can carry embedded scripts.
_SAFE_DATA_URI_RE = re.compile(
r'^data:image/(png|jpeg|gif|webp);base64,', re.IGNORECASE
)
_SAFE_DATA_URI_RE = re.compile(r'^data:image/(png|jpeg|gif|webp);base64,', re.IGNORECASE)
# Exact relative paths accepted as profile images. These are the only
# static-asset paths OWUI itself assigns; no prefix/wildcard matching is
# used so that arbitrary relative paths cannot trigger authenticated GETs
# against internal endpoints when rendered as ``<img>`` sources.
_SAFE_STATIC_PATHS = frozenset({
'/user.png',
'/favicon.png',
'/static/favicon.png',
})
_SAFE_STATIC_PATHS = frozenset(
{
'/user.png',
'/favicon.png',
'/static/favicon.png',
}
)
def validate_profile_image_url(url: str) -> str:
@@ -67,9 +67,7 @@ def validate_profile_image_url(url: str) -> str:
# for a URL like http://:80/path with no actual host).
if parsed.scheme in ('http', 'https'):
if not parsed.hostname:
raise ValueError(
'Invalid profile image URL: HTTP(S) URLs must include a host.'
)
raise ValueError('Invalid profile image URL: HTTP(S) URLs must include a host.')
return url
# Base64-encoded raster images uploaded via the frontend.