diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py
index d0b4ed8f3..a6cffeecd 100644
--- a/backend/open_webui/config.py
+++ b/backend/open_webui/config.py
@@ -1137,6 +1137,10 @@ USER_PERMISSIONS_FEATURES_CODE_INTERPRETER = (
== "true"
)
+USER_PERMISSIONS_FEATURES_NOTES = (
+ os.environ.get("USER_PERMISSIONS_FEATURES_NOTES", "True").lower() == "true"
+)
+
DEFAULT_USER_PERMISSIONS = {
"workspace": {
@@ -1170,6 +1174,7 @@ DEFAULT_USER_PERMISSIONS = {
"web_search": USER_PERMISSIONS_FEATURES_WEB_SEARCH,
"image_generation": USER_PERMISSIONS_FEATURES_IMAGE_GENERATION,
"code_interpreter": USER_PERMISSIONS_FEATURES_CODE_INTERPRETER,
+ "notes": USER_PERMISSIONS_FEATURES_NOTES,
},
}
diff --git a/backend/open_webui/routers/notes.py b/backend/open_webui/routers/notes.py
index a78953bb4..74156dea3 100644
--- a/backend/open_webui/routers/notes.py
+++ b/backend/open_webui/routers/notes.py
@@ -15,7 +15,7 @@ from open_webui.env import SRC_LOG_LEVELS
from open_webui.utils.auth import get_admin_user, get_verified_user
-from open_webui.utils.access_control import has_access
+from open_webui.utils.access_control import has_permission
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
@@ -28,7 +28,16 @@ router = APIRouter()
@router.get("/", response_model=list[NoteUserResponse])
-async def get_notes(user=Depends(get_verified_user)):
+async def get_notes(request: Request, user=Depends(get_verified_user)):
+
+ if user.role != "admin" and not has_permission(
+ user.id, "features.notes", request.app.state.config.USER_PERMISSIONS
+ ):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail=ERROR_MESSAGES.UNAUTHORIZED,
+ )
+
notes = [
NoteUserResponse(
**{
@@ -43,7 +52,16 @@ async def get_notes(user=Depends(get_verified_user)):
@router.get("/list", response_model=list[NoteUserResponse])
-async def get_note_list(user=Depends(get_verified_user)):
+async def get_note_list(request: Request, user=Depends(get_verified_user)):
+
+ if user.role != "admin" and not has_permission(
+ user.id, "features.notes", request.app.state.config.USER_PERMISSIONS
+ ):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail=ERROR_MESSAGES.UNAUTHORIZED,
+ )
+
notes = [
NoteUserResponse(
**{
@@ -63,7 +81,18 @@ async def get_note_list(user=Depends(get_verified_user)):
@router.post("/create", response_model=Optional[NoteModel])
-async def create_new_note(form_data: NoteForm, user=Depends(get_admin_user)):
+async def create_new_note(
+ request: Request, form_data: NoteForm, user=Depends(get_verified_user)
+):
+
+ if user.role != "admin" and not has_permission(
+ user.id, "features.notes", request.app.state.config.USER_PERMISSIONS
+ ):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail=ERROR_MESSAGES.UNAUTHORIZED,
+ )
+
try:
note = Notes.insert_new_note(form_data, user.id)
return note
@@ -80,7 +109,15 @@ async def create_new_note(form_data: NoteForm, user=Depends(get_admin_user)):
@router.get("/{id}", response_model=Optional[NoteModel])
-async def get_note_by_id(id: str, user=Depends(get_verified_user)):
+async def get_note_by_id(request: Request, id: str, user=Depends(get_verified_user)):
+ if user.role != "admin" and not has_permission(
+ user.id, "features.notes", request.app.state.config.USER_PERMISSIONS
+ ):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail=ERROR_MESSAGES.UNAUTHORIZED,
+ )
+
note = Notes.get_note_by_id(id)
if not note:
raise HTTPException(
@@ -104,8 +141,16 @@ async def get_note_by_id(id: str, user=Depends(get_verified_user)):
@router.post("/{id}/update", response_model=Optional[NoteModel])
async def update_note_by_id(
- id: str, form_data: NoteForm, user=Depends(get_verified_user)
+ request: Request, id: str, form_data: NoteForm, user=Depends(get_verified_user)
):
+ if user.role != "admin" and not has_permission(
+ user.id, "features.notes", request.app.state.config.USER_PERMISSIONS
+ ):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail=ERROR_MESSAGES.UNAUTHORIZED,
+ )
+
note = Notes.get_note_by_id(id)
if not note:
raise HTTPException(
@@ -135,7 +180,15 @@ async def update_note_by_id(
@router.delete("/{id}/delete", response_model=bool)
-async def delete_note_by_id(id: str, user=Depends(get_verified_user)):
+async def delete_note_by_id(request: Request, id: str, user=Depends(get_verified_user)):
+ if user.role != "admin" and not has_permission(
+ user.id, "features.notes", request.app.state.config.USER_PERMISSIONS
+ ):
+ raise HTTPException(
+ status_code=status.HTTP_401_UNAUTHORIZED,
+ detail=ERROR_MESSAGES.UNAUTHORIZED,
+ )
+
note = Notes.get_note_by_id(id)
if not note:
raise HTTPException(
diff --git a/backend/open_webui/routers/users.py b/backend/open_webui/routers/users.py
index 0c348f51e..50014a5f6 100644
--- a/backend/open_webui/routers/users.py
+++ b/backend/open_webui/routers/users.py
@@ -129,6 +129,7 @@ class FeaturesPermissions(BaseModel):
web_search: bool = True
image_generation: bool = True
code_interpreter: bool = True
+ notes: bool = True
class UserPermissions(BaseModel):
diff --git a/src/lib/components/admin/Users/Groups.svelte b/src/lib/components/admin/Users/Groups.svelte
index e89b463b0..5847ebbb1 100644
--- a/src/lib/components/admin/Users/Groups.svelte
+++ b/src/lib/components/admin/Users/Groups.svelte
@@ -81,7 +81,8 @@
direct_tool_servers: false,
web_search: true,
image_generation: true,
- code_interpreter: true
+ code_interpreter: true,
+ notes: true
}
};
diff --git a/src/lib/components/admin/Users/Groups/Permissions.svelte b/src/lib/components/admin/Users/Groups/Permissions.svelte
index 9edf20ca0..6af935813 100644
--- a/src/lib/components/admin/Users/Groups/Permissions.svelte
+++ b/src/lib/components/admin/Users/Groups/Permissions.svelte
@@ -37,7 +37,8 @@
direct_tool_servers: false,
web_search: true,
image_generation: true,
- code_interpreter: true
+ code_interpreter: true,
+ notes: true
}
};
@@ -380,5 +381,13 @@