refac
This commit is contained in:
1 parent
783205a965
commit
fe3300bd65
4 files changed
+43
-28
No files matched your search
@@ -27,6 +27,7 @@ from open_webui.utils.oauth import (
|
|||||||
resolve_oauth_client_info,
|
resolve_oauth_client_info,
|
||||||
)
|
)
|
||||||
from open_webui.utils.tools import (
|
from open_webui.utils.tools import (
|
||||||
|
bearer_auth_header,
|
||||||
get_tool_server_data,
|
get_tool_server_data,
|
||||||
get_tool_server_url,
|
get_tool_server_url,
|
||||||
set_terminal_servers,
|
set_terminal_servers,
|
||||||
@@ -351,7 +352,7 @@ async def verify_terminal_server_connection(
|
|||||||
|
|
||||||
headers = {}
|
headers = {}
|
||||||
if form_data.auth_type == 'bearer' and form_data.key:
|
if form_data.auth_type == 'bearer' and form_data.key:
|
||||||
headers['Authorization'] = f'Bearer {form_data.key}'
|
headers.update(bearer_auth_header(form_data.key))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with aiohttp.ClientSession(
|
async with aiohttp.ClientSession(
|
||||||
@@ -423,7 +424,7 @@ async def put_terminal_server_policy(
|
|||||||
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
headers = {'Content-Type': 'application/json'}
|
||||||
if form_data.auth_type == 'bearer' and form_data.key:
|
if form_data.auth_type == 'bearer' and form_data.key:
|
||||||
headers['Authorization'] = f'Bearer {form_data.key}'
|
headers.update(bearer_auth_header(form_data.key))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with aiohttp.ClientSession(
|
async with aiohttp.ClientSession(
|
||||||
@@ -458,7 +459,7 @@ async def put_terminal_server_lifecycle(
|
|||||||
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
headers = {'Content-Type': 'application/json'}
|
||||||
if form_data.auth_type == 'bearer' and form_data.key:
|
if form_data.auth_type == 'bearer' and form_data.key:
|
||||||
headers['Authorization'] = f'Bearer {form_data.key}'
|
headers.update(bearer_auth_header(form_data.key))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with aiohttp.ClientSession(
|
async with aiohttp.ClientSession(
|
||||||
@@ -496,7 +497,7 @@ async def refresh_terminal_server_terminals(
|
|||||||
|
|
||||||
headers = {'Content-Type': 'application/json'}
|
headers = {'Content-Type': 'application/json'}
|
||||||
if form_data.auth_type == 'bearer' and form_data.key:
|
if form_data.auth_type == 'bearer' and form_data.key:
|
||||||
headers['Authorization'] = f'Bearer {form_data.key}'
|
headers.update(bearer_auth_header(form_data.key))
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
'only_idle': form_data.only_idle,
|
'only_idle': form_data.only_idle,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ from open_webui.models.groups import Groups
|
|||||||
from open_webui.models.users import Users
|
from open_webui.models.users import Users
|
||||||
from open_webui.utils.access_control import has_connection_access
|
from open_webui.utils.access_control import has_connection_access
|
||||||
from open_webui.utils.auth import get_verified_user
|
from open_webui.utils.auth import get_verified_user
|
||||||
|
from open_webui.utils.tools import bearer_auth_header, normalize_bearer_token
|
||||||
from starlette.background import BackgroundTask
|
from starlette.background import BackgroundTask
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@@ -126,15 +127,15 @@ async def proxy_terminal(
|
|||||||
auth_type = connection.get('auth_type', 'bearer')
|
auth_type = connection.get('auth_type', 'bearer')
|
||||||
|
|
||||||
if auth_type == 'bearer':
|
if auth_type == 'bearer':
|
||||||
headers['Authorization'] = f'Bearer {connection.get("key", "")}'
|
headers.update(bearer_auth_header(connection.get('key', '')))
|
||||||
elif auth_type == 'session':
|
elif auth_type == 'session':
|
||||||
cookies = request.cookies
|
cookies = request.cookies
|
||||||
headers['Authorization'] = f'Bearer {request.state.token.credentials}'
|
headers.update(bearer_auth_header(request.state.token.credentials))
|
||||||
elif auth_type == 'system_oauth':
|
elif auth_type == 'system_oauth':
|
||||||
cookies = request.cookies
|
cookies = request.cookies
|
||||||
oauth_token = request.headers.get('x-oauth-access-token', '')
|
oauth_token = request.headers.get('x-oauth-access-token', '')
|
||||||
if oauth_token:
|
if oauth_token:
|
||||||
headers['Authorization'] = f'Bearer {oauth_token}'
|
headers.update(bearer_auth_header(oauth_token))
|
||||||
# auth_type == "none": no Authorization header
|
# auth_type == "none": no Authorization header
|
||||||
|
|
||||||
content_type = request.headers.get('content-type')
|
content_type = request.headers.get('content-type')
|
||||||
@@ -309,7 +310,7 @@ async def ws_terminal(
|
|||||||
# First-message auth to upstream terminal server
|
# First-message auth to upstream terminal server
|
||||||
auth_type = connection.get('auth_type', 'bearer')
|
auth_type = connection.get('auth_type', 'bearer')
|
||||||
if auth_type == 'bearer':
|
if auth_type == 'bearer':
|
||||||
key = connection.get('key', '')
|
key = normalize_bearer_token(connection.get('key', ''))
|
||||||
await upstream.send_str(_json.dumps({'type': 'auth', 'token': key}))
|
await upstream.send_str(_json.dumps({'type': 'auth', 'token': key}))
|
||||||
|
|
||||||
await publish_event(
|
await publish_event(
|
||||||
|
|||||||
@@ -103,6 +103,15 @@ from pydantic.fields import FieldInfo
|
|||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_bearer_token(token: Any) -> str:
|
||||||
|
return token.strip() if isinstance(token, str) else token or ''
|
||||||
|
|
||||||
|
|
||||||
|
def bearer_auth_header(token: Any) -> dict[str, str]:
|
||||||
|
token = normalize_bearer_token(token)
|
||||||
|
return {'Authorization': f'Bearer {token}'} if token else {}
|
||||||
|
|
||||||
|
|
||||||
async def build_tool_server_headers(
|
async def build_tool_server_headers(
|
||||||
connection: dict,
|
connection: dict,
|
||||||
request,
|
request,
|
||||||
@@ -1141,7 +1150,7 @@ async def set_terminal_servers(request: Request):
|
|||||||
return
|
return
|
||||||
headers = {}
|
headers = {}
|
||||||
if connection.get('auth_type', 'bearer') == 'bearer':
|
if connection.get('auth_type', 'bearer') == 'bearer':
|
||||||
headers['Authorization'] = f'Bearer {connection.get("key", "")}'
|
headers.update(bearer_auth_header(connection.get('key', '')))
|
||||||
prompt = await get_terminal_system_prompt(server['url'], headers)
|
prompt = await get_terminal_system_prompt(server['url'], headers)
|
||||||
if prompt:
|
if prompt:
|
||||||
server['system_prompt'] = prompt
|
server['system_prompt'] = prompt
|
||||||
@@ -1216,15 +1225,15 @@ async def get_terminal_tools(
|
|||||||
headers = {'Content-Type': 'application/json', 'X-User-Id': user.id}
|
headers = {'Content-Type': 'application/json', 'X-User-Id': user.id}
|
||||||
|
|
||||||
if auth_type == 'bearer':
|
if auth_type == 'bearer':
|
||||||
headers['Authorization'] = f'Bearer {connection.get("key", "")}'
|
headers.update(bearer_auth_header(connection.get('key', '')))
|
||||||
elif auth_type == 'session':
|
elif auth_type == 'session':
|
||||||
cookies = request.cookies
|
cookies = request.cookies
|
||||||
headers['Authorization'] = f'Bearer {request.state.token.credentials}'
|
headers.update(bearer_auth_header(request.state.token.credentials))
|
||||||
elif auth_type == 'system_oauth':
|
elif auth_type == 'system_oauth':
|
||||||
cookies = request.cookies
|
cookies = request.cookies
|
||||||
oauth_token = extra_params.get('__oauth_token__', None)
|
oauth_token = extra_params.get('__oauth_token__', None)
|
||||||
if oauth_token:
|
if oauth_token:
|
||||||
headers['Authorization'] = f'Bearer {oauth_token.get("access_token", "")}'
|
headers.update(bearer_auth_header(oauth_token.get('access_token', '')))
|
||||||
# auth_type == "none": no Authorization header
|
# auth_type == "none": no Authorization header
|
||||||
|
|
||||||
system_prompt = server_data.get('system_prompt')
|
system_prompt = server_data.get('system_prompt')
|
||||||
@@ -1349,7 +1358,7 @@ async def get_tool_servers_data(servers: list[dict[str, Any]]) -> list[dict[str,
|
|||||||
# Fetch from URL
|
# Fetch from URL
|
||||||
task = get_tool_server_data(
|
task = get_tool_server_data(
|
||||||
spec_url,
|
spec_url,
|
||||||
{'Authorization': f'Bearer {token}'} if token else None,
|
bearer_auth_header(token) or None,
|
||||||
)
|
)
|
||||||
elif spec_type == 'json' and server.get('spec', ''):
|
elif spec_type == 'json' and server.get('spec', ''):
|
||||||
# Use provided JSON spec
|
# Use provided JSON spec
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ export type TerminalCwd = {
|
|||||||
|
|
||||||
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
import { WEBUI_API_BASE_URL } from '$lib/constants';
|
||||||
|
|
||||||
|
const bearerHeaders = (apiKey: string): Record<string, string> => ({
|
||||||
|
Authorization: `Bearer ${apiKey.trim()}`
|
||||||
|
});
|
||||||
|
|
||||||
export type TerminalServer = {
|
export type TerminalServer = {
|
||||||
id: string;
|
id: string;
|
||||||
url: string;
|
url: string;
|
||||||
@@ -50,7 +54,7 @@ export const getTerminalConfig = async (
|
|||||||
): Promise<{ features: TerminalFeatures } | null> => {
|
): Promise<{ features: TerminalFeatures } | null> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/api/config`;
|
const url = `${baseUrl.replace(/\/$/, '')}/api/config`;
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
headers: { Authorization: `Bearer ${apiKey}` }
|
headers: bearerHeaders(apiKey)
|
||||||
}).catch(() => null);
|
}).catch(() => null);
|
||||||
if (!res || !res.ok) return null;
|
if (!res || !res.ok) return null;
|
||||||
return res.json().catch(() => null);
|
return res.json().catch(() => null);
|
||||||
@@ -62,7 +66,7 @@ export const getCwd = async (
|
|||||||
sessionId?: string
|
sessionId?: string
|
||||||
): Promise<TerminalCwd | null> => {
|
): Promise<TerminalCwd | null> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/cwd`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/cwd`;
|
||||||
const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
|
const headers: Record<string, string> = bearerHeaders(apiKey);
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
const res = await fetch(url, { headers }).catch(() => null);
|
const res = await fetch(url, { headers }).catch(() => null);
|
||||||
if (!res || !res.ok) return null;
|
if (!res || !res.ok) return null;
|
||||||
@@ -83,7 +87,7 @@ export const listFiles = async (
|
|||||||
): Promise<FileEntry[] | null> => {
|
): Promise<FileEntry[] | null> => {
|
||||||
// The endpoint uses `directory` as the query param name
|
// The endpoint uses `directory` as the query param name
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/list?directory=${encodeURIComponent(path)}`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/list?directory=${encodeURIComponent(path)}`;
|
||||||
const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
|
const headers: Record<string, string> = bearerHeaders(apiKey);
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
const res = await fetch(url, { headers })
|
const res = await fetch(url, { headers })
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
@@ -104,7 +108,7 @@ export const readFile = async (
|
|||||||
sessionId?: string
|
sessionId?: string
|
||||||
): Promise<string | null> => {
|
): Promise<string | null> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/read?path=${encodeURIComponent(path)}`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/read?path=${encodeURIComponent(path)}`;
|
||||||
const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
|
const headers: Record<string, string> = bearerHeaders(apiKey);
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
const res = await fetch(url, { headers }).catch((err) => {
|
const res = await fetch(url, { headers }).catch((err) => {
|
||||||
console.error('open-terminal readFile error:', err);
|
console.error('open-terminal readFile error:', err);
|
||||||
@@ -132,7 +136,7 @@ export const downloadFileBlob = async (
|
|||||||
sessionId?: string
|
sessionId?: string
|
||||||
): Promise<{ blob: Blob; filename: string } | null> => {
|
): Promise<{ blob: Blob; filename: string } | null> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/view?path=${encodeURIComponent(path)}`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/view?path=${encodeURIComponent(path)}`;
|
||||||
const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
|
const headers: Record<string, string> = bearerHeaders(apiKey);
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
const res = await fetch(url, { headers }).catch(() => null);
|
const res = await fetch(url, { headers }).catch(() => null);
|
||||||
|
|
||||||
@@ -151,7 +155,7 @@ export const archiveFromTerminal = async (
|
|||||||
): Promise<{ blob: Blob; filename: string } | null> => {
|
): Promise<{ blob: Blob; filename: string } | null> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/archive`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/archive`;
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
...bearerHeaders(apiKey),
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
};
|
};
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
@@ -180,7 +184,7 @@ export const uploadToTerminal = async (
|
|||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/upload?directory=${encodeURIComponent(directory)}`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/upload?directory=${encodeURIComponent(directory)}`;
|
||||||
const body = new FormData();
|
const body = new FormData();
|
||||||
body.append('file', file);
|
body.append('file', file);
|
||||||
const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
|
const headers: Record<string, string> = bearerHeaders(apiKey);
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -206,7 +210,7 @@ export const createDirectory = async (
|
|||||||
): Promise<{ path: string } | null> => {
|
): Promise<{ path: string } | null> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/mkdir`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/mkdir`;
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
...bearerHeaders(apiKey),
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
};
|
};
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
@@ -233,7 +237,7 @@ export const deleteEntry = async (
|
|||||||
sessionId?: string
|
sessionId?: string
|
||||||
): Promise<{ path: string; type: string } | null> => {
|
): Promise<{ path: string; type: string } | null> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/delete?path=${encodeURIComponent(path)}`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/delete?path=${encodeURIComponent(path)}`;
|
||||||
const headers: Record<string, string> = { Authorization: `Bearer ${apiKey}` };
|
const headers: Record<string, string> = bearerHeaders(apiKey);
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
@@ -258,7 +262,7 @@ export const setCwd = async (
|
|||||||
): Promise<{ cwd: string } | null> => {
|
): Promise<{ cwd: string } | null> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/cwd`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/cwd`;
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
...bearerHeaders(apiKey),
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
};
|
};
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
@@ -287,7 +291,7 @@ export const moveEntry = async (
|
|||||||
): Promise<{ source: string; destination: string } | { error: string }> => {
|
): Promise<{ source: string; destination: string } | { error: string }> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/files/move`;
|
const url = `${baseUrl.replace(/\/$/, '')}/files/move`;
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
...bearerHeaders(apiKey),
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
};
|
};
|
||||||
if (sessionId) headers['X-Session-Id'] = sessionId;
|
if (sessionId) headers['X-Session-Id'] = sessionId;
|
||||||
@@ -313,7 +317,7 @@ export const getListeningPorts = async (
|
|||||||
): Promise<ListeningPort[]> => {
|
): Promise<ListeningPort[]> => {
|
||||||
const url = `${baseUrl.replace(/\/$/, '')}/ports`;
|
const url = `${baseUrl.replace(/\/$/, '')}/ports`;
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
headers: { Authorization: `Bearer ${apiKey}` }
|
headers: bearerHeaders(apiKey)
|
||||||
}).catch(() => null);
|
}).catch(() => null);
|
||||||
if (!res || !res.ok) return [];
|
if (!res || !res.ok) return [];
|
||||||
const json = await res.json().catch(() => null);
|
const json = await res.json().catch(() => null);
|
||||||
@@ -337,7 +341,7 @@ export const createNotebookSession = async (
|
|||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
...bearerHeaders(apiKey),
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ path })
|
body: JSON.stringify({ path })
|
||||||
@@ -370,7 +374,7 @@ export const executeNotebookCell = async (
|
|||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${apiKey}`,
|
...bearerHeaders(apiKey),
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
@@ -397,7 +401,7 @@ export const stopNotebookSession = async (
|
|||||||
const url = `${baseUrl.replace(/\/$/, '')}/notebooks/${sessionId}`;
|
const url = `${baseUrl.replace(/\/$/, '')}/notebooks/${sessionId}`;
|
||||||
const res = await fetch(url, {
|
const res = await fetch(url, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: { Authorization: `Bearer ${apiKey}` }
|
headers: bearerHeaders(apiKey)
|
||||||
}).catch(() => null);
|
}).catch(() => null);
|
||||||
return res?.ok ?? false;
|
return res?.ok ?? false;
|
||||||
};
|
};
|
||||||
Reference in new issue
Block a user