mirror of
https://github.com/langgenius/dify.git
synced 2026-03-28 01:29:55 +08:00
Signed-off-by: -LAN- <laipz8200@outlook.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: WH-2099 <wh2099@pm.me>
104 lines
3.2 KiB
Python
104 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy.sql import Select
|
|
|
|
from models import ToolFile, UploadFile
|
|
from models.enums import CreatorUserRole
|
|
|
|
from .protocols import FileAccessControllerProtocol
|
|
from .scope import FileAccessScope, get_current_file_access_scope
|
|
|
|
|
|
class DatabaseFileAccessController(FileAccessControllerProtocol):
|
|
"""Workflow-layer authorization helper for database-backed file lookups.
|
|
|
|
Tenant scoping remains mandatory. When the current execution belongs to an
|
|
end user, the lookup is additionally constrained to that end user's file
|
|
ownership markers.
|
|
"""
|
|
|
|
_scope_getter: Callable[[], FileAccessScope | None]
|
|
|
|
def __init__(
|
|
self,
|
|
*,
|
|
scope_getter: Callable[[], FileAccessScope | None] = get_current_file_access_scope,
|
|
) -> None:
|
|
self._scope_getter = scope_getter
|
|
|
|
def current_scope(self) -> FileAccessScope | None:
|
|
return self._scope_getter()
|
|
|
|
def apply_upload_file_filters(
|
|
self,
|
|
stmt: Select[tuple[UploadFile]],
|
|
*,
|
|
scope: FileAccessScope | None = None,
|
|
) -> Select[tuple[UploadFile]]:
|
|
resolved_scope = scope or self.current_scope()
|
|
if resolved_scope is None:
|
|
return stmt
|
|
|
|
scoped_stmt = stmt.where(UploadFile.tenant_id == resolved_scope.tenant_id)
|
|
if not resolved_scope.requires_user_ownership:
|
|
return scoped_stmt
|
|
|
|
return scoped_stmt.where(
|
|
UploadFile.created_by_role == CreatorUserRole.END_USER,
|
|
UploadFile.created_by == resolved_scope.user_id,
|
|
)
|
|
|
|
def apply_tool_file_filters(
|
|
self,
|
|
stmt: Select[tuple[ToolFile]],
|
|
*,
|
|
scope: FileAccessScope | None = None,
|
|
) -> Select[tuple[ToolFile]]:
|
|
resolved_scope = scope or self.current_scope()
|
|
if resolved_scope is None:
|
|
return stmt
|
|
|
|
scoped_stmt = stmt.where(ToolFile.tenant_id == resolved_scope.tenant_id)
|
|
if not resolved_scope.requires_user_ownership:
|
|
return scoped_stmt
|
|
|
|
return scoped_stmt.where(ToolFile.user_id == resolved_scope.user_id)
|
|
|
|
def get_upload_file(
|
|
self,
|
|
*,
|
|
session: Session,
|
|
file_id: str,
|
|
scope: FileAccessScope | None = None,
|
|
) -> UploadFile | None:
|
|
resolved_scope = scope or self.current_scope()
|
|
if resolved_scope is None:
|
|
return session.get(UploadFile, file_id)
|
|
|
|
stmt = self.apply_upload_file_filters(
|
|
select(UploadFile).where(UploadFile.id == file_id),
|
|
scope=resolved_scope,
|
|
)
|
|
return session.scalar(stmt)
|
|
|
|
def get_tool_file(
|
|
self,
|
|
*,
|
|
session: Session,
|
|
file_id: str,
|
|
scope: FileAccessScope | None = None,
|
|
) -> ToolFile | None:
|
|
resolved_scope = scope or self.current_scope()
|
|
if resolved_scope is None:
|
|
return session.get(ToolFile, file_id)
|
|
|
|
stmt = self.apply_tool_file_filters(
|
|
select(ToolFile).where(ToolFile.id == file_id),
|
|
scope=resolved_scope,
|
|
)
|
|
return session.scalar(stmt)
|