mirror of
https://github.com/langgenius/dify.git
synced 2026-10-16 15:35:32 +08:00
fix(openapi): refuse web-app access_mode public when the server disables public access
This commit is contained in:
@@ -12,7 +12,11 @@ from pydantic import BaseModel
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from configs import dify_config
|
||||
from controllers.openapi._errors import WebAppAccessModeConsoleOnly, WebAppAccessUnavailable
|
||||
from controllers.openapi._errors import (
|
||||
WebAppAccessModeConsoleOnly,
|
||||
WebAppAccessUnavailable,
|
||||
WebAppPublicAccessDisabled,
|
||||
)
|
||||
from controllers.openapi._models import (
|
||||
AgentAppInfo,
|
||||
AgentAppInfoPatch,
|
||||
@@ -212,6 +216,8 @@ def webapp_access(ctx: Context) -> WebAppAccess:
|
||||
def update_webapp_access(ctx: Context, body: WebAppAccessPayload) -> WebAppAccess:
|
||||
if body.access_mode not in _SETTABLE_ACCESS_MODES:
|
||||
raise WebAppAccessModeConsoleOnly()
|
||||
if body.access_mode == WebAppAccessMode.PUBLIC and not dify_config.WEBAPP_PUBLIC_ACCESS_ENABLED:
|
||||
raise WebAppPublicAccessDisabled()
|
||||
try:
|
||||
_ACCESS_POLICY.update_access_mode(ctx.app.id, body.access_mode)
|
||||
except WebAppAccessUnavailableError as error:
|
||||
|
||||
@@ -83,6 +83,7 @@ class OpenApiErrorCode(StrEnum):
|
||||
NODE_TYPE_NOT_FOUND = "node_type_not_found"
|
||||
NODE_NOT_FOUND = "node_not_found"
|
||||
WEBAPP_ACCESS_MODE_CONSOLE_ONLY = "webapp_access_mode_console_only"
|
||||
WEBAPP_PUBLIC_ACCESS_DISABLED = "webapp_public_access_disabled"
|
||||
SECRET_MASK_NOT_SECRET = "secret_mask_not_secret"
|
||||
MARKETPLACE_DISABLED = "marketplace_disabled"
|
||||
MARKETPLACE_UNAVAILABLE = "marketplace_unavailable"
|
||||
@@ -351,6 +352,13 @@ class WebAppAccessModeConsoleOnly(OpenApiError): # noqa: N818
|
||||
hint = "Use public, private_all or sso_verified here."
|
||||
|
||||
|
||||
class WebAppPublicAccessDisabled(OpenApiError): # noqa: N818
|
||||
code = 403
|
||||
error_code = OpenApiErrorCode.WEBAPP_PUBLIC_ACCESS_DISABLED
|
||||
description = "This server does not allow web apps with access_mode public."
|
||||
hint = "Use private_all or sso_verified."
|
||||
|
||||
|
||||
class VersionNotRestorable(OpenApiError): # noqa: N818
|
||||
code = 400
|
||||
error_code = OpenApiErrorCode.VERSION_NOT_RESTORABLE
|
||||
|
||||
@@ -6,7 +6,7 @@ import pytest
|
||||
|
||||
from controllers.openapi import _app_settings
|
||||
from controllers.openapi._app_settings import WebAppPath
|
||||
from controllers.openapi._errors import WebAppAccessUnavailable
|
||||
from controllers.openapi._errors import WebAppAccessModeConsoleOnly, WebAppAccessUnavailable, WebAppPublicAccessDisabled
|
||||
from controllers.openapi._models import WebAppAccessPayload
|
||||
from controllers.openapi.auth.context import Context
|
||||
from enums import WebAppAccessMode
|
||||
@@ -43,6 +43,53 @@ def test_set_webapp_access_returns_the_written_mode_without_reading_back(monkeyp
|
||||
policy.update_access_mode.assert_called_once_with("app-1", WebAppAccessMode.PRIVATE_ALL)
|
||||
|
||||
|
||||
def test_set_webapp_access_public_is_refused_when_the_server_disables_public_access(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.setattr(_app_settings.dify_config, "WEBAPP_PUBLIC_ACCESS_ENABLED", False)
|
||||
policy = Mock()
|
||||
monkeypatch.setattr(_app_settings, "_ACCESS_POLICY", policy)
|
||||
|
||||
with pytest.raises(WebAppPublicAccessDisabled):
|
||||
_app_settings.update_webapp_access(_context(), WebAppAccessPayload(access_mode=WebAppAccessMode.PUBLIC))
|
||||
|
||||
policy.update_access_mode.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", [WebAppAccessMode.PRIVATE_ALL, WebAppAccessMode.SSO_VERIFIED])
|
||||
def test_set_webapp_access_non_public_modes_are_unaffected_by_the_public_switch(
|
||||
monkeypatch: pytest.MonkeyPatch, mode: WebAppAccessMode
|
||||
) -> None:
|
||||
monkeypatch.setattr(_app_settings.dify_config, "WEBAPP_PUBLIC_ACCESS_ENABLED", False)
|
||||
policy = Mock()
|
||||
monkeypatch.setattr(_app_settings, "_ACCESS_POLICY", policy)
|
||||
|
||||
result = _app_settings.update_webapp_access(_context(), WebAppAccessPayload(access_mode=mode))
|
||||
|
||||
assert result.access_mode == mode
|
||||
policy.update_access_mode.assert_called_once_with("app-1", mode)
|
||||
|
||||
|
||||
def test_set_webapp_access_public_is_written_when_the_server_allows_it(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setattr(_app_settings.dify_config, "WEBAPP_PUBLIC_ACCESS_ENABLED", True)
|
||||
policy = Mock()
|
||||
monkeypatch.setattr(_app_settings, "_ACCESS_POLICY", policy)
|
||||
|
||||
result = _app_settings.update_webapp_access(_context(), WebAppAccessPayload(access_mode=WebAppAccessMode.PUBLIC))
|
||||
|
||||
assert result.access_mode == WebAppAccessMode.PUBLIC
|
||||
policy.update_access_mode.assert_called_once_with("app-1", WebAppAccessMode.PUBLIC)
|
||||
|
||||
|
||||
def test_set_webapp_access_private_still_answers_console_only_when_public_is_disabled(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.setattr(_app_settings.dify_config, "WEBAPP_PUBLIC_ACCESS_ENABLED", False)
|
||||
|
||||
with pytest.raises(WebAppAccessModeConsoleOnly):
|
||||
_app_settings.update_webapp_access(_context(), WebAppAccessPayload(access_mode=WebAppAccessMode.PRIVATE))
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("mode", "path"),
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user