feat: implement global memories toggle and permissions (#20462)
This commit is contained in:
@@ -1470,6 +1470,10 @@ USER_PERMISSIONS_FEATURES_API_KEYS = (
|
|||||||
os.environ.get("USER_PERMISSIONS_FEATURES_API_KEYS", "False").lower() == "true"
|
os.environ.get("USER_PERMISSIONS_FEATURES_API_KEYS", "False").lower() == "true"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
USER_PERMISSIONS_FEATURES_MEMORIES = (
|
||||||
|
os.environ.get("USER_PERMISSIONS_FEATURES_MEMORIES", "True").lower() == "true"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
USER_PERMISSIONS_SETTINGS_INTERFACE = (
|
USER_PERMISSIONS_SETTINGS_INTERFACE = (
|
||||||
os.environ.get("USER_PERMISSIONS_SETTINGS_INTERFACE", "True").lower() == "true"
|
os.environ.get("USER_PERMISSIONS_SETTINGS_INTERFACE", "True").lower() == "true"
|
||||||
@@ -1533,6 +1537,7 @@ DEFAULT_USER_PERMISSIONS = {
|
|||||||
"web_search": USER_PERMISSIONS_FEATURES_WEB_SEARCH,
|
"web_search": USER_PERMISSIONS_FEATURES_WEB_SEARCH,
|
||||||
"image_generation": USER_PERMISSIONS_FEATURES_IMAGE_GENERATION,
|
"image_generation": USER_PERMISSIONS_FEATURES_IMAGE_GENERATION,
|
||||||
"code_interpreter": USER_PERMISSIONS_FEATURES_CODE_INTERPRETER,
|
"code_interpreter": USER_PERMISSIONS_FEATURES_CODE_INTERPRETER,
|
||||||
|
"memories": USER_PERMISSIONS_FEATURES_MEMORIES,
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"interface": USER_PERMISSIONS_SETTINGS_INTERFACE,
|
"interface": USER_PERMISSIONS_SETTINGS_INTERFACE,
|
||||||
@@ -2083,6 +2088,12 @@ ENABLE_CODE_INTERPRETER = PersistentConfig(
|
|||||||
os.environ.get("ENABLE_CODE_INTERPRETER", "True").lower() == "true",
|
os.environ.get("ENABLE_CODE_INTERPRETER", "True").lower() == "true",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ENABLE_MEMORIES = PersistentConfig(
|
||||||
|
"ENABLE_MEMORIES",
|
||||||
|
"memories.enable",
|
||||||
|
os.environ.get("ENABLE_MEMORIES", "True").lower() == "true",
|
||||||
|
)
|
||||||
|
|
||||||
CODE_INTERPRETER_ENGINE = PersistentConfig(
|
CODE_INTERPRETER_ENGINE = PersistentConfig(
|
||||||
"CODE_INTERPRETER_ENGINE",
|
"CODE_INTERPRETER_ENGINE",
|
||||||
"code_interpreter.engine",
|
"code_interpreter.engine",
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ from open_webui.config import (
|
|||||||
CODE_INTERPRETER_JUPYTER_AUTH_TOKEN,
|
CODE_INTERPRETER_JUPYTER_AUTH_TOKEN,
|
||||||
CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD,
|
CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD,
|
||||||
CODE_INTERPRETER_JUPYTER_TIMEOUT,
|
CODE_INTERPRETER_JUPYTER_TIMEOUT,
|
||||||
|
ENABLE_MEMORIES,
|
||||||
# Image
|
# Image
|
||||||
AUTOMATIC1111_API_AUTH,
|
AUTOMATIC1111_API_AUTH,
|
||||||
AUTOMATIC1111_BASE_URL,
|
AUTOMATIC1111_BASE_URL,
|
||||||
@@ -1106,6 +1107,7 @@ app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT = CODE_INTERPRETER_JUPYTER_TIM
|
|||||||
app.state.config.IMAGE_GENERATION_ENGINE = IMAGE_GENERATION_ENGINE
|
app.state.config.IMAGE_GENERATION_ENGINE = IMAGE_GENERATION_ENGINE
|
||||||
app.state.config.ENABLE_IMAGE_GENERATION = ENABLE_IMAGE_GENERATION
|
app.state.config.ENABLE_IMAGE_GENERATION = ENABLE_IMAGE_GENERATION
|
||||||
app.state.config.ENABLE_IMAGE_PROMPT_GENERATION = ENABLE_IMAGE_PROMPT_GENERATION
|
app.state.config.ENABLE_IMAGE_PROMPT_GENERATION = ENABLE_IMAGE_PROMPT_GENERATION
|
||||||
|
app.state.config.ENABLE_MEMORIES = ENABLE_MEMORIES
|
||||||
|
|
||||||
app.state.config.IMAGE_GENERATION_MODEL = IMAGE_GENERATION_MODEL
|
app.state.config.IMAGE_GENERATION_MODEL = IMAGE_GENERATION_MODEL
|
||||||
app.state.config.IMAGE_SIZE = IMAGE_SIZE
|
app.state.config.IMAGE_SIZE = IMAGE_SIZE
|
||||||
@@ -1935,6 +1937,7 @@ async def get_app_config(request: Request):
|
|||||||
"enable_admin_chat_access": ENABLE_ADMIN_CHAT_ACCESS,
|
"enable_admin_chat_access": ENABLE_ADMIN_CHAT_ACCESS,
|
||||||
"enable_google_drive_integration": app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
|
"enable_google_drive_integration": app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
|
||||||
"enable_onedrive_integration": app.state.config.ENABLE_ONEDRIVE_INTEGRATION,
|
"enable_onedrive_integration": app.state.config.ENABLE_ONEDRIVE_INTEGRATION,
|
||||||
|
"enable_memories": app.state.config.ENABLE_MEMORIES,
|
||||||
**(
|
**(
|
||||||
{
|
{
|
||||||
"enable_onedrive_personal": ENABLE_ONEDRIVE_PERSONAL,
|
"enable_onedrive_personal": ENABLE_ONEDRIVE_PERSONAL,
|
||||||
|
|||||||
@@ -991,6 +991,7 @@ async def get_admin_config(request: Request, user=Depends(get_admin_user)):
|
|||||||
"ENABLE_FOLDERS": request.app.state.config.ENABLE_FOLDERS,
|
"ENABLE_FOLDERS": request.app.state.config.ENABLE_FOLDERS,
|
||||||
"FOLDER_MAX_FILE_COUNT": request.app.state.config.FOLDER_MAX_FILE_COUNT,
|
"FOLDER_MAX_FILE_COUNT": request.app.state.config.FOLDER_MAX_FILE_COUNT,
|
||||||
"ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS,
|
"ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS,
|
||||||
|
"ENABLE_MEMORIES": request.app.state.config.ENABLE_MEMORIES,
|
||||||
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
|
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
|
||||||
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
|
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
|
||||||
"PENDING_USER_OVERLAY_TITLE": request.app.state.config.PENDING_USER_OVERLAY_TITLE,
|
"PENDING_USER_OVERLAY_TITLE": request.app.state.config.PENDING_USER_OVERLAY_TITLE,
|
||||||
@@ -1015,6 +1016,7 @@ class AdminConfig(BaseModel):
|
|||||||
ENABLE_FOLDERS: bool
|
ENABLE_FOLDERS: bool
|
||||||
FOLDER_MAX_FILE_COUNT: Optional[int | str] = None
|
FOLDER_MAX_FILE_COUNT: Optional[int | str] = None
|
||||||
ENABLE_CHANNELS: bool
|
ENABLE_CHANNELS: bool
|
||||||
|
ENABLE_MEMORIES: bool
|
||||||
ENABLE_NOTES: bool
|
ENABLE_NOTES: bool
|
||||||
ENABLE_USER_WEBHOOKS: bool
|
ENABLE_USER_WEBHOOKS: bool
|
||||||
PENDING_USER_OVERLAY_TITLE: Optional[str] = None
|
PENDING_USER_OVERLAY_TITLE: Optional[str] = None
|
||||||
@@ -1046,6 +1048,7 @@ async def update_admin_config(
|
|||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
request.app.state.config.ENABLE_CHANNELS = form_data.ENABLE_CHANNELS
|
request.app.state.config.ENABLE_CHANNELS = form_data.ENABLE_CHANNELS
|
||||||
|
request.app.state.config.ENABLE_MEMORIES = form_data.ENABLE_MEMORIES
|
||||||
request.app.state.config.ENABLE_NOTES = form_data.ENABLE_NOTES
|
request.app.state.config.ENABLE_NOTES = form_data.ENABLE_NOTES
|
||||||
|
|
||||||
if form_data.DEFAULT_USER_ROLE in ["pending", "user", "admin"]:
|
if form_data.DEFAULT_USER_ROLE in ["pending", "user", "admin"]:
|
||||||
@@ -1091,6 +1094,7 @@ async def update_admin_config(
|
|||||||
"ENABLE_FOLDERS": request.app.state.config.ENABLE_FOLDERS,
|
"ENABLE_FOLDERS": request.app.state.config.ENABLE_FOLDERS,
|
||||||
"FOLDER_MAX_FILE_COUNT": request.app.state.config.FOLDER_MAX_FILE_COUNT,
|
"FOLDER_MAX_FILE_COUNT": request.app.state.config.FOLDER_MAX_FILE_COUNT,
|
||||||
"ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS,
|
"ENABLE_CHANNELS": request.app.state.config.ENABLE_CHANNELS,
|
||||||
|
"ENABLE_MEMORIES": request.app.state.config.ENABLE_MEMORIES,
|
||||||
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
|
"ENABLE_NOTES": request.app.state.config.ENABLE_NOTES,
|
||||||
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
|
"ENABLE_USER_WEBHOOKS": request.app.state.config.ENABLE_USER_WEBHOOKS,
|
||||||
"PENDING_USER_OVERLAY_TITLE": request.app.state.config.PENDING_USER_OVERLAY_TITLE,
|
"PENDING_USER_OVERLAY_TITLE": request.app.state.config.PENDING_USER_OVERLAY_TITLE,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -10,11 +10,16 @@ from open_webui.utils.auth import get_verified_user
|
|||||||
from open_webui.internal.db import get_session
|
from open_webui.internal.db import get_session
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from open_webui.utils.access_control import has_permission
|
||||||
|
from open_webui.constants import ERROR_MESSAGES
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/ef")
|
@router.get("/ef")
|
||||||
async def get_embeddings(request: Request):
|
async def get_embeddings(request: Request):
|
||||||
return {"result": await request.app.state.EMBEDDING_FUNCTION("hello world")}
|
return {"result": await request.app.state.EMBEDDING_FUNCTION("hello world")}
|
||||||
@@ -26,7 +31,21 @@ async def get_embeddings(request: Request):
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/", response_model=list[MemoryModel])
|
@router.get("/", response_model=list[MemoryModel])
|
||||||
async def get_memories(user=Depends(get_verified_user), db: Session = Depends(get_session)):
|
async def get_memories(
|
||||||
|
request: Request, user=Depends(get_verified_user), db: Session = Depends(get_session)
|
||||||
|
):
|
||||||
|
if not request.app.state.config.ENABLE_MEMORIES:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=ERROR_MESSAGES.NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not has_permission(user.id, "features.memories", request.app.state.config.USER_PERMISSIONS):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
return Memories.get_memories_by_user_id(user.id, db=db)
|
return Memories.get_memories_by_user_id(user.id, db=db)
|
||||||
|
|
||||||
|
|
||||||
@@ -50,6 +69,18 @@ async def add_memory(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
if not request.app.state.config.ENABLE_MEMORIES:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=ERROR_MESSAGES.NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not has_permission(user.id, "features.memories", request.app.state.config.USER_PERMISSIONS):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
memory = Memories.insert_new_memory(user.id, form_data.content, db=db)
|
memory = Memories.insert_new_memory(user.id, form_data.content, db=db)
|
||||||
|
|
||||||
vector = await request.app.state.EMBEDDING_FUNCTION(memory.content, user=user)
|
vector = await request.app.state.EMBEDDING_FUNCTION(memory.content, user=user)
|
||||||
@@ -83,6 +114,18 @@ class QueryMemoryForm(BaseModel):
|
|||||||
async def query_memory(
|
async def query_memory(
|
||||||
request: Request, form_data: QueryMemoryForm, user=Depends(get_verified_user), db: Session = Depends(get_session)
|
request: Request, form_data: QueryMemoryForm, user=Depends(get_verified_user), db: Session = Depends(get_session)
|
||||||
):
|
):
|
||||||
|
if not request.app.state.config.ENABLE_MEMORIES:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=ERROR_MESSAGES.NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not has_permission(user.id, "features.memories", request.app.state.config.USER_PERMISSIONS):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
memories = Memories.get_memories_by_user_id(user.id, db=db)
|
memories = Memories.get_memories_by_user_id(user.id, db=db)
|
||||||
if not memories:
|
if not memories:
|
||||||
raise HTTPException(status_code=404, detail="No memories found for user")
|
raise HTTPException(status_code=404, detail="No memories found for user")
|
||||||
@@ -105,6 +148,18 @@ async def query_memory(
|
|||||||
async def reset_memory_from_vector_db(
|
async def reset_memory_from_vector_db(
|
||||||
request: Request, user=Depends(get_verified_user), db: Session = Depends(get_session)
|
request: Request, user=Depends(get_verified_user), db: Session = Depends(get_session)
|
||||||
):
|
):
|
||||||
|
if not request.app.state.config.ENABLE_MEMORIES:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=ERROR_MESSAGES.NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not has_permission(user.id, "features.memories", request.app.state.config.USER_PERMISSIONS):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
VECTOR_DB_CLIENT.delete_collection(f"user-memory-{user.id}")
|
VECTOR_DB_CLIENT.delete_collection(f"user-memory-{user.id}")
|
||||||
|
|
||||||
memories = Memories.get_memories_by_user_id(user.id, db=db)
|
memories = Memories.get_memories_by_user_id(user.id, db=db)
|
||||||
@@ -142,7 +197,21 @@ async def reset_memory_from_vector_db(
|
|||||||
|
|
||||||
|
|
||||||
@router.delete("/delete/user", response_model=bool)
|
@router.delete("/delete/user", response_model=bool)
|
||||||
async def delete_memory_by_user_id(user=Depends(get_verified_user), db: Session = Depends(get_session)):
|
async def delete_memory_by_user_id(
|
||||||
|
request: Request, user=Depends(get_verified_user), db: Session = Depends(get_session)
|
||||||
|
):
|
||||||
|
if not request.app.state.config.ENABLE_MEMORIES:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=ERROR_MESSAGES.NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not has_permission(user.id, "features.memories", request.app.state.config.USER_PERMISSIONS):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
result = Memories.delete_memories_by_user_id(user.id, db=db)
|
result = Memories.delete_memories_by_user_id(user.id, db=db)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
@@ -168,6 +237,18 @@ async def update_memory_by_id(
|
|||||||
user=Depends(get_verified_user),
|
user=Depends(get_verified_user),
|
||||||
db: Session = Depends(get_session),
|
db: Session = Depends(get_session),
|
||||||
):
|
):
|
||||||
|
if not request.app.state.config.ENABLE_MEMORIES:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=ERROR_MESSAGES.NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not has_permission(user.id, "features.memories", request.app.state.config.USER_PERMISSIONS):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
memory = Memories.update_memory_by_id_and_user_id(
|
memory = Memories.update_memory_by_id_and_user_id(
|
||||||
memory_id, user.id, form_data.content, db=db
|
memory_id, user.id, form_data.content, db=db
|
||||||
)
|
)
|
||||||
@@ -201,7 +282,21 @@ async def update_memory_by_id(
|
|||||||
|
|
||||||
|
|
||||||
@router.delete("/{memory_id}", response_model=bool)
|
@router.delete("/{memory_id}", response_model=bool)
|
||||||
async def delete_memory_by_id(memory_id: str, user=Depends(get_verified_user), db: Session = Depends(get_session)):
|
async def delete_memory_by_id(
|
||||||
|
memory_id: str, request: Request, user=Depends(get_verified_user), db: Session = Depends(get_session)
|
||||||
|
):
|
||||||
|
if not request.app.state.config.ENABLE_MEMORIES:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=ERROR_MESSAGES.NOT_FOUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not has_permission(user.id, "features.memories", request.app.state.config.USER_PERMISSIONS):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||||
|
)
|
||||||
|
|
||||||
result = Memories.delete_memory_by_id_and_user_id(memory_id, user.id, db=db)
|
result = Memories.delete_memory_by_id_and_user_id(memory_id, user.id, db=db)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ class FeaturesPermissions(BaseModel):
|
|||||||
web_search: bool = True
|
web_search: bool = True
|
||||||
image_generation: bool = True
|
image_generation: bool = True
|
||||||
code_interpreter: bool = True
|
code_interpreter: bool = True
|
||||||
|
memories: bool = True
|
||||||
|
|
||||||
|
|
||||||
class SettingsPermissions(BaseModel):
|
class SettingsPermissions(BaseModel):
|
||||||
|
|||||||
@@ -741,6 +741,14 @@
|
|||||||
<Switch bind:state={adminConfig.ENABLE_CHANNELS} />
|
<Switch bind:state={adminConfig.ENABLE_CHANNELS} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-2.5 flex w-full items-center justify-between pr-2">
|
||||||
|
<div class=" self-center text-xs font-medium">
|
||||||
|
{$i18n.t('Memories')} ({$i18n.t('Beta')})
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Switch bind:state={adminConfig.ENABLE_MEMORIES} />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mb-2.5 flex w-full items-center justify-between pr-2">
|
<div class="mb-2.5 flex w-full items-center justify-between pr-2">
|
||||||
<div class=" self-center text-xs font-medium">
|
<div class=" self-center text-xs font-medium">
|
||||||
{$i18n.t('User Webhooks')}
|
{$i18n.t('User Webhooks')}
|
||||||
|
|||||||
@@ -782,6 +782,22 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col w-full">
|
||||||
|
<div class="flex w-full justify-between my-1">
|
||||||
|
<div class=" self-center text-xs font-medium">
|
||||||
|
{$i18n.t('Memories')}
|
||||||
|
</div>
|
||||||
|
<Switch bind:state={permissions.features.memories} />
|
||||||
|
</div>
|
||||||
|
{#if defaultPermissions?.features?.memories && !permissions.features.memories}
|
||||||
|
<div>
|
||||||
|
<div class="text-xs text-gray-500">
|
||||||
|
{$i18n.t('This is a default user permission and will remain enabled.')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class=" border-gray-100/30 dark:border-gray-850/30" />
|
<hr class=" border-gray-100/30 dark:border-gray-850/30" />
|
||||||
|
|||||||
@@ -491,6 +491,13 @@
|
|||||||
return $user?.role === 'admin' || ($user?.permissions?.settings?.interface ?? true);
|
return $user?.role === 'admin' || ($user?.permissions?.settings?.interface ?? true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tab.id === 'personalization') {
|
||||||
|
return (
|
||||||
|
$config?.features?.enable_memories &&
|
||||||
|
($user?.role === 'admin' || ($user?.permissions?.features?.memories ?? true))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ export const DEFAULT_PERMISSIONS = {
|
|||||||
direct_tool_servers: false,
|
direct_tool_servers: false,
|
||||||
web_search: true,
|
web_search: true,
|
||||||
image_generation: true,
|
image_generation: true,
|
||||||
code_interpreter: true
|
code_interpreter: true,
|
||||||
|
memories: true
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
interface: true
|
interface: true
|
||||||
|
|||||||
@@ -273,6 +273,7 @@ type Config = {
|
|||||||
enable_admin_export: boolean;
|
enable_admin_export: boolean;
|
||||||
enable_admin_chat_access: boolean;
|
enable_admin_chat_access: boolean;
|
||||||
enable_community_sharing: boolean;
|
enable_community_sharing: boolean;
|
||||||
|
enable_memories: boolean;
|
||||||
enable_autocomplete_generation: boolean;
|
enable_autocomplete_generation: boolean;
|
||||||
enable_direct_connections: boolean;
|
enable_direct_connections: boolean;
|
||||||
enable_version_update_check: boolean;
|
enable_version_update_check: boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user