Commit Graph
106 Commits
Author SHA1 Message Date
Timothy Jaeryang Baek 5cdcdbaeec refac 2026-06-17 02:52:35 +02:00
Timothy Jaeryang Baek fbcdcf146b refac 2026-06-16 23:59:24 +02:00
Timothy Jaeryang Baek 7e9d41d664 refac 2026-05-19 20:44:38 +04:00
Timothy Jaeryang Baek c75fe8e74b fix: get_image_base64_from_file_id 2026-05-19 20:33:46 +04:00
Timothy Jaeryang Baek 6d0295588e refac: modernize type annotations (PEP 604 / PEP 585) 2026-05-12 17:10:15 +09:00
Timothy Jaeryang Baek 4856ce48be chore: format 2026-05-11 02:51:59 +09:00
Timothy Jaeryang Baek 0037baeb26 enh: channels streaming agent 2026-05-11 02:50:30 +09:00
Classic298 f5e110fbee fix: enforce message ownership in group/DM channel update + delete endpoints (#24506)
* fix: enforce message ownership in group/DM channel update + delete endpoints

`update_message_by_id` (channels.py:1348) and `delete_message_by_id`
(channels.py:1550) branch on `channel.type`. The `else` branch (standard
channels) correctly enforces `message.user_id != user.id` ownership before
mutating, but the `if channel.type in ['group', 'dm']` branch only checked
`is_user_channel_member` — channel membership alone, with no message
ownership verification.

Effect on group/DM channels: any verified member of the conversation could:

- overwrite another member's message content while the server preserved
  `user_id=victim`, producing tampered content that renders to other
  members as the original author's authentic post (integrity + authenticity);
- silently delete another member's messages, removing them from
  conversation history without trace (integrity).

Reproduced end-to-end against v0.9.4 with three users (attacker, victim,
viewer) sharing a group channel: attacker overwrites victim's message and
deletes another, viewer reads the tampered content as victim-authored.

Two patches, identical shape, mirror the `else` branch's existing
ownership semantics:

- `update_message_by_id` group/DM branch: add
  `if user.role != 'admin' and message.user_id != user.id: raise 403`
  immediately after the `is_user_channel_member` check.
- `delete_message_by_id` group/DM branch: same.

The standard-channel branch is unchanged (it already enforced ownership).
Admins remain able to moderate any message, matching the existing semantic
in the standard-channel branch.

Reports consolidated under GHSA-wwhq-cx22-f7vv (earliest live filing of the
group/DM-specific variant). Same gap previously surfaced and partially
fixed under GHSA-jxwr-g6r6-j3fx (which addressed the standard-channel
branch only) — this completes the cohort.

* chore: trim comments
2026-05-11 01:03:39 +09:00
Classic298andkikayli d3737176bc fix: require write permission for pin_channel_message on standard channels (#24521)
`pin_channel_message` (channels.py:1242) checked `permission='read'` on
the standard-channel branch before mutating `is_pinned` / `pinned_by` /
`pinned_at` via `Messages.update_is_pinned_by_id`. Pin/unpin is a write
operation; gating it on read access let any user with read-only channel
access pin or unpin any message in the channel, including admin posts.

One-character fix: change `permission='read'` to `permission='write'`.

Reported by kikayli in GHSA-5gc6-xhv4-2wg6.

Co-authored-by: kikayli <kikayli@users.noreply.github.com>
2026-05-11 00:59:50 +09:00
Timothy Jaeryang Baek c7b6de6ca4 refac 2026-04-21 15:41:07 +09:00
Classic298andClaude b3ca943da1 perf(channels): batch user lookup in model_response_handler thread history (#23795)
* perf(channels): batch user lookup in model_response_handler thread history

The thread-history builder in model_response_handler called
Users.get_user_by_id once per thread message (deduped via an intra-loop
dict), producing N individual SELECTs for a thread of N unique authors.

Replace with a single Users.get_users_by_user_ids call that returns all
authors in one WHERE id IN (...) query, matching the batch pattern
already used elsewhere in this file (lines 739, 804, 1320).

Behavior is preserved: deleted users still resolve to None and fall
through to the existing 'Unknown' fallback via .get().

* refac(channels): rename loop vars to full words per review

Address reviewer feedback to use descriptive names `message` and `user`
instead of single-letter `m` and `u` in the batch user-lookup
comprehensions.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-20 08:37:07 +09:00
Timothy Jaeryang Baek d0188f3fe1 refac 2026-04-13 14:08:58 -05:00
Timothy Jaeryang Baek 25898116ea chore: format 2026-04-12 18:12:59 -05:00
Classic298 4f94d21780 fix: enforce filter_allowed_access_grants on channel create and update (#23638)
Unlike all other resource routers (knowledge, models, notes, prompts, tools, skills), the channel router did not call filter_allowed_access_grants. This allowed any user to set wildcard access grants on group channels, bypassing the admin's public sharing permission framework.

Adds filter_allowed_access_grants with the sharing.public_channels permission key to both create and update endpoints, matching the pattern used by all other resource routers.
2026-04-12 16:27:44 -05:00
Timothy Jaeryang Baek 27169124f2 refac: async db 2026-04-12 14:22:11 -05:00
Classic298 b618d84065 fix: add missing read-access check on channel members endpoint (#23625)
The GET /channels/{id}/members endpoint checked membership for group/dm channels but had no access gate for standard channels, allowing any authenticated user with channels permission to enumerate members of private standard channels by UUID.
2026-04-12 12:41:51 -05:00
G30 92dfa3f2f2 fix(backend): provide fallback strings for webhook UserNameResponse to prevent Pydantic validation error (#23414) 2026-04-11 17:10:11 -06:00
Timothy Jaeryang Baek 6acaaea59a refac 2026-04-11 15:23:37 -06:00
Timothy Jaeryang Baek 9d3e0637c8 refac 2026-04-02 02:05:35 -05:00
Tim Baek c24a4da17d refac 2026-03-24 14:54:29 -05:00
Timothy Jaeryang Baek ade617efa8 refac 2026-03-24 04:49:48 -05:00
Timothy Jaeryang Baek 945275faae refac 2026-03-22 06:58:58 -05:00
Timothy Jaeryang Baek de3317e26b refac 2026-03-17 17:58:01 -05:00
Timothy Jaeryang Baek 2cacc2e649 chore: format 2026-03-01 13:34:09 -06:00
Timothy Jaeryang Baek c9a78e5476 refac 2026-03-01 13:30:36 -06:00
Timothy Jaeryang Baek b36f8d9314 chore: format 2026-02-13 15:00:47 -06:00
Timothy Jaeryang Baek ca6b18ab5c refac: is_user_active 2026-02-13 13:40:59 -06:00
Timothy Jaeryang Baek 8919d8a82a refac 2026-02-12 15:52:50 -06:00
Classic298andTim Baek ea4ef28da5 init (#20883)
Co-authored-by: Tim Baek <tim@openwebui.com>
2026-02-12 15:50:13 -06:00
Timothy Jaeryang Baek f376d4f378 chore: format 2026-02-11 16:24:11 -06:00
Timothy Jaeryang Baek f7406ff576 refac 2026-02-09 13:28:14 -06:00
G30 cac5dd12e9 fix: handle null data in model_response_handler (#21112)
Fix `AttributeError` in `model_response_handler` when processing channel messages with `null` data field. The function iterates over thread messages to build conversation history, but some messages may have `data=None` causing a crash when accessing `thread_message.data.get()`. Added null check using `(thread_message.data or {}).get("files", [])` to safely handle messages without data.
2026-02-05 15:15:34 -05:00
Timothy Jaeryang Baek 3bec320bb9 refac 2026-01-23 01:23:34 +04:00
Timothy Jaeryang Baek 14e51e0977 refac 2026-01-23 01:02:41 +04:00
Timothy Jaeryang Baek 7da37b4f66 refac 2026-01-12 21:41:23 +04:00
Classic298 41d1ccd39c Update channels.py (#20546) 2026-01-10 15:34:12 +04:00
Timothy Jaeryang Baek b377e5ff4c chore: format 2026-01-09 02:46:04 +04:00
Timothy Jaeryang Baek cd296fcf0d feat: channel webhooks 2026-01-09 02:30:15 +04:00
Timothy Jaeryang Baek 700349064d chore: format 2026-01-08 01:55:56 +04:00
Classic298 48f1b2d547 fix(channels): eliminate N+1 query in get_pinned_messages endpoint (#20459)
Replaced per-message user lookup with batch fetch using SQL IN clause.

Changes:
- Fetch all message user_ids in a single pass
- Use Users.get_users_by_user_ids() for batch lookup
- Build user mapping to avoid DB calls in loop
- Add early return for empty message lists

Performance: Reduces N+1 queries to 2 queries (messages + users)
2026-01-07 23:36:38 +04:00
Classic298 b8fb9e815b fix(channels): eliminate N+1 query in get_channel_messages endpoint (#20458)
Replaced per-message user lookup with batch fetch using SQL IN clause.

Changes:
- Fetch all message user_ids in a single pass
- Use Users.get_users_by_user_ids() for batch lookup
- Build user mapping to avoid DB calls in loop
- Add early return for empty message lists

Performance: Reduces N+1 queries to 2 queries (messages + users)
2026-01-07 23:36:12 +04:00
Classic298 74974334a5 fix: More n+1 channel perf fixes (#20460) 2026-01-07 23:34:19 +04:00
Timothy Jaeryang Baek 5649a668fa refac 2025-12-29 01:42:13 +04:00
Timothy Jaeryang Baek 2453b75ff0 refac 2025-12-29 01:31:27 +04:00
Timothy Jaeryang Baek 5d1459df16 refac 2025-12-29 01:20:04 +04:00
Timothy Jaeryang Baek 5995771583 fix: channel model mention 2025-12-23 10:42:33 +04:00
823b9a6dd9 chore/perf: Remove old SRC level log env vars with no impact (#20045)
* Update openai.py

* Update env.py

* Merge pull request open-webui#19030 from open-webui/dev (#119)

Co-authored-by: Tim Baek <tim@openwebui.com>
Co-authored-by: Claude <noreply@anthropic.com>

---------

Co-authored-by: Tim Baek <tim@openwebui.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-20 08:16:14 -05:00
G30 d65116282c fix: enforce global ENABLE_CHANNELS check on all channel endpoints (#19957)
* fix: enforce global ENABLE_CHANNELS check on all channel endpoints

When channels are disabled globally (ENABLE_CHANNELS=false), users with
channel permissions could still fetch channels via API endpoints. This
fix adds a get_enabled_channels dependency to all 22 channel endpoints
that returns 403 Forbidden when channels are globally disabled.

Fixes #19914

* refac

* refac
2025-12-20 08:15:29 -05:00
Timothy Jaeryang Baek 79cfe29bb2 refac: channel_file and knowledge table migration 2025-12-10 16:41:22 -05:00
Timothy Jaeryang Baek 6fe737bf8f refac 2025-12-03 19:31:23 -05:00