Skip to content
Merged

Dev #267

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
180 commits
Select commit Hold shift + click to select a range
32c68e0
i18n: improve zh-CN translation
ShirasawaSama Feb 23, 2026
ec4fe4f
i18n: improve zh-TW translation
ShirasawaSama Feb 23, 2026
22f074c
fix: dictation toggle shortcuts i18n
EntropyYue Feb 23, 2026
8962afd
Merge pull request #21784 from ShirasawaSama/i18n/improve-chinese-tra…
tjbck Feb 23, 2026
6ab452a
Merge pull request #21785 from EventHorizon-AI/fix/shortcuts-i18n
tjbck Feb 23, 2026
140ab27
fix: correct ENABLE_AUDIT_STDOUT stdout filter (#21777)
jannikstdl Feb 23, 2026
3761b3a
refac
tjbck Feb 23, 2026
febc66e
enh: sbom docker gh action
tjbck Feb 23, 2026
8f49725
refac
tjbck Feb 23, 2026
f4a1d99
refac
tjbck Feb 23, 2026
1808d7f
feat: sort action buttons by valve priority (#21790)
Classic298 Feb 23, 2026
a52e6c2
Filter by public/private (#21797)
pljones Feb 23, 2026
3d99de6
enh: access grant level perms
tjbck Feb 23, 2026
176f9a7
refac
tjbck Feb 23, 2026
3c8d658
fix: tools_dict issue
tjbck Feb 23, 2026
0b86759
refac
tjbck Feb 24, 2026
e6fe3ba
refac
tjbck Feb 24, 2026
2461121
refac
tjbck Feb 24, 2026
b36e55c
refac
tjbck Feb 24, 2026
64ec736
refac
tjbck Feb 24, 2026
0b6c92b
refac
tjbck Feb 24, 2026
538501c
refac
tjbck Feb 24, 2026
5c403fb
fix: resolve valve priority for actions and filters via class instant…
Classic298 Feb 24, 2026
958fbdd
refac
tjbck Feb 24, 2026
7a16e49
Update print statement from 'Hello' to 'Goodbye' (#21842)
Classic298 Feb 24, 2026
62e7e0b
refac
tjbck Feb 24, 2026
9478c5e
refac
tjbck Feb 24, 2026
82959ce
Update oauth_sessions.py (#21794)
Classic298 Feb 24, 2026
81781e6
refac
tjbck Feb 24, 2026
5ee5093
refac
tjbck Feb 24, 2026
184e921
refac
tjbck Feb 25, 2026
e3f21d6
Update SECURITY.md (#21859)
Classic298 Feb 25, 2026
9dff497
refac
tjbck Feb 25, 2026
b2413f9
perf: early-return in get_tools() for empty tool_ids (#21873)
Algorithm5838 Feb 25, 2026
39e3f8f
fix(sidebar): lock user menu position when sidebar is resized (#21853)
silentoplayz Feb 25, 2026
50f95a4
refac
tjbck Feb 25, 2026
5beb37c
i18n(pt-BR): add translations for newly added UI items + consistency …
joaoback Feb 25, 2026
ace69bb
refac
tjbck Feb 25, 2026
acb2147
refac
tjbck Feb 25, 2026
484ba91
refac
tjbck Feb 25, 2026
fd91fa4
refac
tjbck Feb 25, 2026
87d33f6
refac
tjbck Feb 25, 2026
f0c71e5
refac
tjbck Feb 25, 2026
636ab99
feat: experimental open terminal integration
tjbck Feb 25, 2026
345f3e3
refac
tjbck Feb 25, 2026
64ff15a
refac
tjbck Feb 25, 2026
bee13f7
refac
tjbck Feb 25, 2026
8b2160f
refac
tjbck Feb 25, 2026
3271a52
refac
tjbck Feb 25, 2026
f2c3fff
refac
tjbck Feb 25, 2026
c522503
refac
tjbck Feb 25, 2026
cb01658
refac
tjbck Feb 25, 2026
50e6a19
refac
tjbck Feb 26, 2026
1f77691
refac
tjbck Feb 26, 2026
819ea0d
refac
tjbck Feb 26, 2026
b1f2929
refac
tjbck Feb 26, 2026
5a08084
refac
tjbck Feb 26, 2026
c303388
refac
tjbck Feb 26, 2026
1cb74b0
refac
tjbck Feb 26, 2026
50eff6a
refac
tjbck Feb 26, 2026
46229a9
refac
tjbck Feb 26, 2026
44ed941
refac
tjbck Feb 26, 2026
58d685e
refac
tjbck Feb 26, 2026
eca9b40
refac
tjbck Feb 26, 2026
5921453
refac
tjbck Feb 26, 2026
419ea1c
refac
tjbck Feb 26, 2026
d7d05a4
fix(ui): fix some broken links (#21904)
stweil Feb 26, 2026
527d36e
Update catalan translation.json (#21895)
aleixdorca Feb 26, 2026
4654ecb
perf: fast-path comparison in ResponseMessage to skip JSON.stringify …
Classic298 Feb 26, 2026
7ea6afd
perf: cache KaTeX module import as singleton across all renderer inst…
Classic298 Feb 26, 2026
4737e1f
feat: open terminal integration
tjbck Feb 27, 2026
4731ccb
refac
tjbck Feb 27, 2026
bbab64b
refac
tjbck Feb 27, 2026
646b64a
refac
tjbck Feb 27, 2026
44ab77b
refac
tjbck Feb 27, 2026
d6d9d1c
refac
tjbck Feb 27, 2026
5d821d2
refac
tjbck Feb 27, 2026
0f8b339
refac
tjbck Feb 27, 2026
758d8fc
refac
tjbck Feb 27, 2026
965f242
refac
tjbck Feb 27, 2026
6b01f96
refac
tjbck Feb 27, 2026
e7a9988
chore: format
tjbck Feb 27, 2026
2d82d26
refac
tjbck Feb 27, 2026
179a4ad
refac
tjbck Feb 27, 2026
a677b21
refac
tjbck Feb 27, 2026
0324a1b
refac
tjbck Feb 27, 2026
f60d386
refac
tjbck Feb 27, 2026
cfa16e1
refac
tjbck Feb 27, 2026
bbbcf27
refac
tjbck Feb 27, 2026
3be0613
refac
tjbck Feb 27, 2026
3a6c88a
refac
tjbck Feb 27, 2026
83b17e2
refac
tjbck Feb 27, 2026
9544a80
refac
tjbck Feb 27, 2026
c60b0fa
refac
tjbck Feb 27, 2026
5ac502e
refac
tjbck Feb 27, 2026
ab3f03b
refac
tjbck Feb 28, 2026
f5bf2a2
refac
tjbck Feb 28, 2026
c71beb0
refac
tjbck Feb 28, 2026
18401de
upd:i18n es-ES language update v0.8.5 (#21956)
rgaricano Feb 28, 2026
144c0f3
fix: fix missing i18n keys (#21932)
ShirasawaSama Feb 28, 2026
242b3f0
fix: Fix Tooltip memory leaking and type define (#21969)
ShirasawaSama Feb 28, 2026
5bb1c42
fix: Fix memory leaking of MessageInput (#21968)
ShirasawaSama Feb 28, 2026
9440d09
refac
tjbck Feb 28, 2026
54cefed
perf: use structuredClone for message deep copies (#21948)
Algorithm5838 Feb 28, 2026
ff8cf80
fix: fix memory leaking of Notes.svelte (#21963)
ShirasawaSama Feb 28, 2026
fc5f399
perf: batch scrollToBottom during streaming via rAF (#21946)
Algorithm5838 Feb 28, 2026
f722633
i18n: improve Chinese translation (#21934)
ShirasawaSama Feb 28, 2026
c3bac9a
refac
tjbck Feb 28, 2026
6b462ff
refac
tjbck Feb 28, 2026
e9b5eb6
fix: Fix memory leaking in create model page (#21966)
ShirasawaSama Feb 28, 2026
2d27ef4
refac
tjbck Feb 28, 2026
40d9028
I18n: improve Chinese translation (#21980)
ShirasawaSama Feb 28, 2026
499ca28
refac
tjbck Feb 28, 2026
30ae519
perf: throttle message list rebuild to once per animation frame durin…
Classic298 Feb 28, 2026
aed2f69
chore: Changelog updates (#21791)
Classic298 Feb 28, 2026
a3de0bc
refac
tjbck Mar 1, 2026
668bd44
refac
tjbck Mar 1, 2026
43c3042
refac
tjbck Mar 1, 2026
1357dc6
chore: format
tjbck Mar 1, 2026
7dda802
refac
tjbck Mar 1, 2026
e83f668
refac
tjbck Mar 1, 2026
39b87d9
fix: Fix memory leaking in MentionList.svelte (#21965)
ShirasawaSama Mar 1, 2026
ae28e7d
refac
tjbck Mar 1, 2026
234306f
refac
tjbck Mar 1, 2026
3d535db
refac
tjbck Mar 1, 2026
d2b3812
refac
tjbck Mar 1, 2026
ed1b959
refac
tjbck Mar 1, 2026
769ef85
chore: format
tjbck Mar 1, 2026
18865a9
refac
tjbck Mar 1, 2026
ddedceb
refac
tjbck Mar 1, 2026
c37c0e3
Update translation.json (#22096)
Classic298 Mar 1, 2026
a9d8348
i18n(pt-BR): add translations for newly added UI items + consistency …
joaoback Mar 1, 2026
fe604a8
bugfix: Prevent double toast on single hide/show toggle (#22079)
pljones Mar 1, 2026
6d7f21b
fix: fix memory leaking of SIdebar (#22082)
ShirasawaSama Mar 1, 2026
391a487
perf: replace JSON.parse(JSON.stringify()) with structuredClone in la…
Classic298 Mar 1, 2026
73617ec
perf: fast-path length check in StatusHistory comparison (#22103)
Classic298 Mar 1, 2026
a0d6c20
perf: fast-path token comparison in CodeBlock (#22101)
Classic298 Mar 1, 2026
3569280
perf: replace JSON.parse(JSON.stringify()) with structuredClone in Ch…
Classic298 Mar 1, 2026
1db36b5
refac
tjbck Mar 1, 2026
c436e03
perf: async DB calls, skip intermediate status writes, elif chain in …
Classic298 Mar 1, 2026
1b89bee
perf: add fast-path comparison in MultiResponseMessages (#22100)
Classic298 Mar 1, 2026
e901111
perf: skip redundant object spread in buildMessages (#22086)
Algorithm5838 Mar 1, 2026
ff86283
refac
tjbck Mar 1, 2026
0b851cf
fix: offline model retrieval, re-raise to disable instead of returnin…
Classic298 Mar 1, 2026
5f304e5
chore: changelog (#22080)
Classic298 Mar 1, 2026
d415edc
chore: bump
tjbck Mar 1, 2026
fcff9c3
refac
tjbck Mar 1, 2026
0fff2fb
refac
tjbck Mar 1, 2026
62ab30f
refac
tjbck Mar 1, 2026
2cbba2a
chore: format
tjbck Mar 1, 2026
c9a78e5
refac
tjbck Mar 1, 2026
2cacc2e
chore: format
tjbck Mar 1, 2026
c83a421
refac
tjbck Mar 1, 2026
387225e
fix: suppress internal path leakage in audio transcription errors (GH…
Classic298 Mar 1, 2026
597883a
perf: use structuredClone and fast-path comparison in UserMessage (#2…
Classic298 Mar 1, 2026
259d5ca
refac
tjbck Mar 1, 2026
93bab8d
refac
tjbck Mar 1, 2026
2054ee0
fix: enforce ownership check on user-memory collection queries (#22109)
Classic298 Mar 1, 2026
9904566
fix: fix memory leaking in Chat.svelte (#21962)
ShirasawaSama Mar 1, 2026
80ad5fd
refac
tjbck Mar 1, 2026
0c2e427
chore: format
tjbck Mar 1, 2026
201b93b
refac
tjbck Mar 1, 2026
5645d5b
refac
tjbck Mar 1, 2026
6863ca4
perf: use rAF to debounce getContents() during streaming
Algorithm5838 Mar 1, 2026
ff9f761
refac
tjbck Mar 1, 2026
2e8c4da
refac
tjbck Mar 1, 2026
67893b9
fix: fix memory leaking in CodeEditor (#22110)
ShirasawaSama Mar 1, 2026
9c9a18d
Merge pull request #21971 from open-webui/dev
tjbck Mar 1, 2026
860a0b4
Merge pull request #22111 from Algorithm5838/perf/debounce-get-contents
tjbck Mar 1, 2026
fe837d8
fix: pass params when saving a temporary chat
Algorithm5838 Mar 1, 2026
702906a
Merge pull request #22119 from Algorithm5838/fix/save-temp-chat-params
tjbck Mar 2, 2026
a9e9fe7
fix: fix memory leaking of ChatControls (#22112)
ShirasawaSama Mar 2, 2026
2751a0f
refac
tjbck Mar 2, 2026
d1dd449
doc: changelog
tjbck Mar 2, 2026
832d018
chore: format
tjbck Mar 2, 2026
6137f7c
Merge pull request #22121 from open-webui/dev
tjbck Mar 2, 2026
568c97c
Merge remote-tracking branch 'openwebui/main' into dev
OrenZhang Mar 2, 2026
f14096f
chore(repo): merge from remote
OrenZhang Mar 2, 2026
ac47849
feat(ChatControls): add TypeScript support to module script
OrenZhang Mar 2, 2026
0201904
chore(repo): merge from remote
OrenZhang Mar 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/docker-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ jobs:
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=registry,ref=${{ steps.cache-meta.outputs.tags }}
cache-to: type=registry,ref=${{ steps.cache-meta.outputs.tags }},mode=max
sbom: true
build-args: |
BUILD_HASH=${{ github.sha }}
USE_SLIM=true
Expand Down
76 changes: 76 additions & 0 deletions CHANGELOG.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions CHANGELOG_EXTRA.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.8.7.1] - 2026.03.02

### Changed

- 合并官方 0.8.7 改动

## [0.8.5.1] - 2026.02.24

### Changed
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTOR_LICENSE_AGREEMENT
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Open WebUI Contributor License Agreement
# Contributor License Agreement

By submitting my contributions to Open WebUI, I grant Open WebUI full freedom to use my work in any way they choose, under any terms they like, both now and in the future. This approach helps ensure the project remains unified, flexible, and easy to maintain, while empowering Open WebUI to respond quickly to the needs of its users and the wider community.
By submitting my contributions to this repository in any form, I grant Open WebUI Inc. a perpetual, worldwide, irrevocable, royalty-free license, under copyright and patent, to use, modify, distribute, sublicense, and commercialize my work under any terms they choose, both now and in the future.

Taking part in this process means my work can be seamlessly integrated and combined with others, ensuring longevity and adaptability for everyone who benefits from the Open WebUI project. This collaborative approach strengthens the project’s future and helps guarantee that improvements can always be shared and distributed in the most effective way possible.
I represent that my contributions are my original work (or that I have sufficient rights to grant this license) and that I have the authority to enter into this agreement.

**_To the fullest extent permitted by law, my contributions are provided on an “as is” basis, with no warranties or guarantees of any kind, and I disclaim any liability for any issues or damages arising from their use or incorporation into the project, regardless of the type of legal claim._**
56 changes: 49 additions & 7 deletions backend/open_webui/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ def __getattr__(self, key):
if JWT_EXPIRES_IN.value == "-1":
log.warning(
"⚠️ SECURITY WARNING: JWT_EXPIRES_IN is set to '-1'\n"
" See: https://docs.openwebui.com/getting-started/env-configuration\n"
" See: https://docs.openwebui.com/reference/env-configuration\n"
)

####################################
Expand Down Expand Up @@ -618,6 +618,18 @@ def __getattr__(self, key):
os.environ.get("OAUTH_UPDATE_PICTURE_ON_LOGIN", "False").lower() == "true",
)

OAUTH_UPDATE_NAME_ON_LOGIN = PersistentConfig(
"OAUTH_UPDATE_NAME_ON_LOGIN",
"oauth.update_name_on_login",
os.environ.get("OAUTH_UPDATE_NAME_ON_LOGIN", "False").lower() == "true",
)

OAUTH_UPDATE_EMAIL_ON_LOGIN = PersistentConfig(
"OAUTH_UPDATE_EMAIL_ON_LOGIN",
"oauth.update_email_on_login",
os.environ.get("OAUTH_UPDATE_EMAIL_ON_LOGIN", "False").lower() == "true",
)

OAUTH_ACCESS_TOKEN_REQUEST_INCLUDE_CLIENT_ID = (
os.environ.get("OAUTH_ACCESS_TOKEN_REQUEST_INCLUDE_CLIENT_ID", "False").lower()
== "true"
Expand Down Expand Up @@ -1103,6 +1115,20 @@ def reachable(host: str, port: int) -> bool:
tool_server_connections,
)

####################################
# TERMINAL_SERVER
####################################

terminal_server_connections = json.loads(
os.environ.get("TERMINAL_SERVER_CONNECTIONS", "[]")
)

TERMINAL_SERVER_CONNECTIONS = PersistentConfig(
"TERMINAL_SERVER_CONNECTIONS",
"terminal_server.connections",
terminal_server_connections,
)

####################################
# WEBUI
####################################
Expand Down Expand Up @@ -1401,6 +1427,11 @@ def reachable(host: str, port: int) -> bool:
== "true"
)

USER_PERMISSIONS_ACCESS_GRANTS_ALLOW_USERS = (
os.environ.get("USER_PERMISSIONS_ACCESS_GRANTS_ALLOW_USERS", "True").lower()
== "true"
)

USER_PERMISSIONS_CHAT_CONTROLS = (
os.environ.get("USER_PERMISSIONS_CHAT_CONTROLS", "True").lower() == "true"
)
Expand Down Expand Up @@ -1554,6 +1585,9 @@ def reachable(host: str, port: int) -> bool:
"notes": USER_PERMISSIONS_NOTES_ALLOW_SHARING,
"public_notes": USER_PERMISSIONS_NOTES_ALLOW_PUBLIC_SHARING,
},
"access_grants": {
"allow_users": USER_PERMISSIONS_ACCESS_GRANTS_ALLOW_USERS,
},
"chat": {
"controls": USER_PERMISSIONS_CHAT_CONTROLS,
"valves": USER_PERMISSIONS_CHAT_VALVES,
Expand Down Expand Up @@ -3113,17 +3147,25 @@ class BannerModel(BaseModel):
int(os.getenv("WEB_SEARCH_RESULT_COUNT", "3")),
)


try:
web_search_domain_filter_list = json.loads(
os.getenv("WEB_SEARCH_DOMAIN_FILTER_LIST", "[]")
)
except Exception as e:
web_search_domain_filter_list = [
# "wikipedia.com",
# "wikimedia.org",
# "wikidata.org",
# "!stackoverflow.com",
]

# You can provide a list of your own websites to filter after performing a web search.
# This ensures the highest level of safety and reliability of the information sources.
WEB_SEARCH_DOMAIN_FILTER_LIST = PersistentConfig(
"WEB_SEARCH_DOMAIN_FILTER_LIST",
"rag.web.search.domain.filter_list",
[
# "wikipedia.com",
# "wikimedia.org",
# "wikidata.org",
# "!stackoverflow.com",
],
web_search_domain_filter_list,
)

WEB_SEARCH_CONCURRENT_REQUESTS = PersistentConfig(
Expand Down
13 changes: 13 additions & 0 deletions backend/open_webui/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -1047,3 +1047,16 @@ def parse_section(section):
####################################

EXTERNAL_PWA_MANIFEST_URL = os.environ.get("EXTERNAL_PWA_MANIFEST_URL")

####################################
# GROUP DEFAULTS
####################################

# Controls the default "Who can share to this group" setting for new groups.
# Env var values: "true" (anyone), "false" (no one), "members" (only group members).
_default_group_share = (
os.environ.get("DEFAULT_GROUP_SHARE_PERMISSION", "members").strip().lower()
)
DEFAULT_GROUP_SHARE_PERMISSION = (
"members" if _default_group_share == "members" else _default_group_share == "true"
)
22 changes: 20 additions & 2 deletions backend/open_webui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
utils,
scim,
credit,
terminals,
)

from open_webui.routers.retrieval import (
Expand Down Expand Up @@ -126,6 +127,8 @@
THREAD_POOL_SIZE,
# Tool Server Configs
TOOL_SERVER_CONNECTIONS,
# Terminal Server
TERMINAL_SERVER_CONNECTIONS,
# Code Execution
ENABLE_CODE_EXECUTION,
CODE_EXECUTION_ENGINE,
Expand Down Expand Up @@ -547,7 +550,7 @@
process_chat_payload,
process_chat_response,
)
from open_webui.utils.tools import set_tool_servers
from open_webui.utils.tools import set_tool_servers, set_terminal_servers

from open_webui.utils.auth import (
get_license_data,
Expand Down Expand Up @@ -713,8 +716,13 @@ async def lifespan(app: FastAPI):
)
await set_tool_servers(mock_request)
log.info(f"Initialized {len(app.state.TOOL_SERVERS)} tool server(s)")

await set_terminal_servers(mock_request)
log.info(
f"Initialized {len(app.state.TERMINAL_SERVERS)} terminal server(s)"
)
except Exception as e:
log.warning(f"Failed to initialize tool servers at startup: {e}")
log.warning(f"Failed to initialize tool/terminal servers at startup: {e}")

yield

Expand Down Expand Up @@ -796,6 +804,15 @@ async def lifespan(app: FastAPI):
app.state.config.TOOL_SERVER_CONNECTIONS = TOOL_SERVER_CONNECTIONS
app.state.TOOL_SERVERS = []

########################################
#
# TERMINAL SERVER
#
########################################

app.state.config.TERMINAL_SERVER_CONNECTIONS = TERMINAL_SERVER_CONNECTIONS
app.state.TERMINAL_SERVERS = []

########################################
#
# DIRECT CONNECTIONS
Expand Down Expand Up @@ -1597,6 +1614,7 @@ async def inspect_websocket(request: Request, call_next):
if ENABLE_ADMIN_ANALYTICS:
app.include_router(analytics.router, prefix="/api/v1/analytics", tags=["analytics"])
app.include_router(utils.router, prefix="/api/v1/utils", tags=["utils"])
app.include_router(terminals.router, prefix="/api/v1/terminals", tags=["terminals"])

# SCIM 2.0 API for identity management
if ENABLE_SCIM:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ def upgrade() -> None:

timestamp = message.get("timestamp", now)

try:
timestamp = int(float(timestamp))
except Exception as e:
timestamp = now

# Normalize timestamp: convert ms to seconds, validate range
if timestamp > 10_000_000_000:
timestamp = timestamp // 1000
Expand Down
37 changes: 37 additions & 0 deletions backend/open_webui/models/access_grants.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,43 @@ def has_public_read_access_grant(access_grants: Optional[list]) -> bool:
return False


def has_user_access_grant(access_grants: Optional[list]) -> bool:
"""
Returns True when a direct grant list includes any non-wildcard user grant.
"""
for grant in normalize_access_grants(access_grants):
if grant["principal_type"] == "user" and grant["principal_id"] != "*":
return True
return False


def strip_user_access_grants(access_grants: Optional[list]) -> list:
"""
Remove all non-wildcard user grants from the list.
Keeps group grants and the public wildcard (user:*) intact.
"""
if not access_grants:
return []
return [
grant
for grant in access_grants
if not (
(
grant.get("principal_type")
if isinstance(grant, dict)
else getattr(grant, "principal_type", None)
)
== "user"
and (
grant.get("principal_id")
if isinstance(grant, dict)
else getattr(grant, "principal_id", None)
)
!= "*"
)
]


def grants_to_access_control(grants: list) -> Optional[dict]:
"""
Convert a list of grant objects (AccessGrantModel or AccessGrantResponse)
Expand Down
7 changes: 5 additions & 2 deletions backend/open_webui/models/auths.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def authenticate_user(
def authenticate_user_by_api_key(
self, api_key: str, db: Optional[Session] = None
) -> Optional[UserModel]:
log.info(f"authenticate_user_by_api_key: {api_key}")
log.info(f"authenticate_user_by_api_key")
# if no api_key, return None
if not api_key:
return None
Expand Down Expand Up @@ -197,7 +197,10 @@ def update_email_by_id(
with get_db_context(db) as db:
result = db.query(Auth).filter_by(id=id).update({"email": email})
db.commit()
return True if result == 1 else False
if result == 1:
Users.update_user_by_id(id, {"email": email}, db=db)
return True
return False
except Exception:
return False

Expand Down
21 changes: 20 additions & 1 deletion backend/open_webui/models/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from sqlalchemy.orm import Session
from open_webui.internal.db import Base, JSONField, get_db, get_db_context
from open_webui.env import DEFAULT_GROUP_SHARE_PERMISSION

from open_webui.models.files import FileMetadataResponse

Expand Down Expand Up @@ -130,13 +131,26 @@ class GroupListResponse(BaseModel):


class GroupTable:
def _ensure_default_share_config(self, group_data: dict) -> dict:
"""Ensure the group data dict has a default share config if not already set."""
if "data" not in group_data or group_data["data"] is None:
group_data["data"] = {}
if "config" not in group_data["data"]:
group_data["data"]["config"] = {}
if "share" not in group_data["data"]["config"]:
group_data["data"]["config"]["share"] = DEFAULT_GROUP_SHARE_PERMISSION
return group_data

def insert_new_group(
self, user_id: str, form_data: GroupForm, db: Optional[Session] = None
) -> Optional[GroupModel]:
with get_db_context(db) as db:
group_data = self._ensure_default_share_config(
form_data.model_dump(exclude_none=True)
)
group = GroupModel(
**{
**form_data.model_dump(exclude_none=True),
**group_data,
"id": str(uuid.uuid4()),
"user_id": user_id,
"created_at": int(time.time()),
Expand Down Expand Up @@ -504,6 +518,11 @@ def create_groups_by_group_names(
user_id=user_id,
name=group_name,
description="",
data={
"config": {
"share": DEFAULT_GROUP_SHARE_PERMISSION,
}
},
created_at=int(time.time()),
updated_at=int(time.time()),
)
Expand Down
15 changes: 15 additions & 0 deletions backend/open_webui/models/knowledge.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,21 @@ def add_file_to_knowledge_by_id(
except Exception:
return None

def has_file(
self, knowledge_id: str, file_id: str, db: Optional[Session] = None
) -> bool:
"""Check whether a file belongs to a knowledge base."""
try:
with get_db_context(db) as db:
return (
db.query(KnowledgeFile)
.filter_by(knowledge_id=knowledge_id, file_id=file_id)
.first()
is not None
)
except Exception:
return False

def remove_file_from_knowledge_by_id(
self, knowledge_id: str, file_id: str, db: Optional[Session] = None
) -> bool:
Expand Down
Loading
Loading