mirror of
https://github.com/onyx-dot-app/onyx.git
synced 2026-10-19 01:50:51 -05:00
fix(enterprise-settings): remove the Hide Onyx Branding toggle (#15112)
This commit is contained in:
1 parent
0c6a8e3bcf
commit
f61e05131f
32 files changed
+75
-194
No files matched your search
@@ -200,10 +200,8 @@ def admin_ee_put_settings(
|
||||
settings: EnterpriseSettings,
|
||||
_: User = Depends(require_permission(Permission.FULL_ADMIN_PANEL_ACCESS)),
|
||||
) -> None:
|
||||
# Custom help link and Onyx-branding toggle are Enterprise-only. Block
|
||||
# writes to those fields when tier < ENTERPRISE so the FE disabled state
|
||||
# cannot be bypassed by crafting a request. Uses FEATURE_NOT_AVAILABLE
|
||||
# (402) to match the tier_gate middleware shape.
|
||||
# Custom help link is Enterprise-only. Enforced here so a crafted request
|
||||
# cannot bypass the disabled field in the UI.
|
||||
if not tier_at_least(get_tier(), Tier.ENTERPRISE):
|
||||
existing = load_settings()
|
||||
if (
|
||||
@@ -214,11 +212,6 @@ def admin_ee_put_settings(
|
||||
OnyxErrorCode.FEATURE_NOT_AVAILABLE,
|
||||
"Custom help link requires the Enterprise plan.",
|
||||
)
|
||||
if settings.hide_onyx_branding != existing.hide_onyx_branding:
|
||||
raise OnyxError(
|
||||
OnyxErrorCode.FEATURE_NOT_AVAILABLE,
|
||||
"Hiding Onyx branding requires the Enterprise plan.",
|
||||
)
|
||||
|
||||
store_settings(settings)
|
||||
|
||||
|
||||
@@ -111,9 +111,6 @@ class EnterpriseSettings(BaseModel):
|
||||
custom_help_link_url: str | None = None
|
||||
custom_help_link_label: str | None = None
|
||||
|
||||
# hide the "Powered by Onyx" tagline under the sidebar logo
|
||||
hide_onyx_branding: bool | None = None
|
||||
|
||||
@field_validator("custom_help_link_url")
|
||||
@classmethod
|
||||
def _validate_help_link_scheme(cls, v: str | None) -> str | None:
|
||||
|
||||
@@ -79,6 +79,10 @@ DISABLE_USER_KNOWLEDGE = os.environ.get("DISABLE_USER_KNOWLEDGE", "").lower() ==
|
||||
# are disabled but core chat, tools, user file uploads, and Projects still work.
|
||||
DISABLE_VECTOR_DB = os.environ.get("DISABLE_VECTOR_DB", "").lower() == "true"
|
||||
|
||||
# Hides the "Powered by Onyx" tagline on Enterprise deployments. Do not set
|
||||
# without explicit permission from Onyx.
|
||||
HIDE_ONYX_BRANDING = os.environ.get("HIDE_ONYX_BRANDING", "").lower() == "true"
|
||||
|
||||
# TEMPORARY (will be removed soon): operator-forced Search-UI scope (self-hosted only) —
|
||||
# comma-separated document set NAMES. When set, the Onyx Search UI is restricted to those sets
|
||||
# (AND'd on top of any persona/user scope; ACL still enforced) — chat/other flows are unaffected,
|
||||
|
||||
@@ -10,6 +10,7 @@ from onyx.auth.users import is_user_admin
|
||||
from onyx.configs.app_configs import (
|
||||
DEFAULT_USER_FILE_MAX_UPLOAD_SIZE_MB,
|
||||
DISABLE_VECTOR_DB,
|
||||
HIDE_ONYX_BRANDING,
|
||||
MAX_ALLOWED_UPLOAD_SIZE_MB,
|
||||
POSTHOG_API_KEY,
|
||||
POSTHOG_HOST,
|
||||
@@ -170,6 +171,11 @@ def fetch_settings(
|
||||
apply_license_status_to_settings,
|
||||
)
|
||||
general_settings = apply_fn(general_settings)
|
||||
# The EE apply_fn resolves tier on every path. On CE the stored value is
|
||||
# client-writable, so it never counts.
|
||||
resolved_tier = (
|
||||
general_settings.tier if global_version.is_ee_version() else Tier.COMMUNITY
|
||||
)
|
||||
|
||||
# Craft workspace instructions are visible to authenticated users (they
|
||||
# appear in sandbox AGENTS.md anyway) but not to anonymous visitors.
|
||||
@@ -202,6 +208,8 @@ def fetch_settings(
|
||||
onyx_craft_available=onyx_craft_available,
|
||||
opencode_debugging_enabled=ENABLE_OPENCODE_DEBUGGING,
|
||||
vector_db_enabled=not DISABLE_VECTOR_DB,
|
||||
hide_onyx_branding=HIDE_ONYX_BRANDING
|
||||
and tier_at_least(resolved_tier, Tier.ENTERPRISE),
|
||||
hooks_enabled=not MULTI_TENANT,
|
||||
version=onyx_version,
|
||||
max_allowed_upload_size_mb=MAX_ALLOWED_UPLOAD_SIZE_MB,
|
||||
|
||||
@@ -128,6 +128,8 @@ class UserSettings(Settings):
|
||||
# False when DISABLE_VECTOR_DB is set — connectors, RAG search, and
|
||||
# document sets are unavailable.
|
||||
vector_db_enabled: bool = True
|
||||
# HIDE_ONYX_BRANDING env var, honored only on the Enterprise tier.
|
||||
hide_onyx_branding: bool = False
|
||||
# True when hooks are available: single-tenant EE deployments only.
|
||||
hooks_enabled: bool = False
|
||||
# Application version, read from the ONYX_VERSION env var at startup.
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from ee.onyx.server.enterprise_settings.store import load_settings, store_settings
|
||||
|
||||
|
||||
def test_legacy_hide_onyx_branding_is_dropped_on_load_and_save() -> None:
|
||||
kv_store = MagicMock()
|
||||
kv_store.load.return_value = {
|
||||
"application_name": "Acme",
|
||||
"hide_onyx_branding": True,
|
||||
}
|
||||
|
||||
with patch(
|
||||
"ee.onyx.server.enterprise_settings.store.get_kv_store",
|
||||
return_value=kv_store,
|
||||
):
|
||||
settings = load_settings()
|
||||
store_settings(settings)
|
||||
|
||||
assert settings.application_name == "Acme"
|
||||
assert "hide_onyx_branding" not in settings.model_dump()
|
||||
stored = kv_store.store.call_args.args[1]
|
||||
assert "hide_onyx_branding" not in stored
|
||||
assert stored["application_name"] == "Acme"
|
||||
-2
@@ -167,8 +167,6 @@ services:
|
||||
- NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=${NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED:-}
|
||||
# Enterprise Edition only
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
# DO NOT TURN ON unless you have EXPLICIT PERMISSION from Onyx.
|
||||
- NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
|
||||
- NODE_OPTIONS=${NODE_OPTIONS:-"--max-old-space-size=4096"}
|
||||
env_file:
|
||||
- path: .env
|
||||
|
||||
@@ -208,8 +208,6 @@ services:
|
||||
- NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=${NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED:-}
|
||||
# Enterprise Edition only
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
# DO NOT TURN ON unless you have EXPLICIT PERMISSION from Onyx.
|
||||
- NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
|
||||
- NODE_OPTIONS=${NODE_OPTIONS:-"--max-old-space-size=4096"}
|
||||
env_file:
|
||||
- path: .env
|
||||
|
||||
@@ -409,6 +409,8 @@ LOG_ONYX_MODEL_INTERACTIONS=False
|
||||
# SALESFORCE_CLIENT_SECRET=
|
||||
|
||||
## Miscellaneous
|
||||
# Hides "Powered by Onyx" on Enterprise. Do not set without explicit permission from Onyx.
|
||||
# HIDE_ONYX_BRANDING=
|
||||
# Kill switch for the gateway's native Anthropic passthrough (server tools,
|
||||
# thinking-block signatures, fine-grained streaming); default on. Set to false
|
||||
# to send Anthropic-backed providers back through the OpenAI-translation path.
|
||||
@@ -428,7 +430,6 @@ LOG_ONYX_MODEL_INTERACTIONS=False
|
||||
# NEXT_PUBLIC_DISABLE_LOGOUT=
|
||||
# NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=
|
||||
# NEXT_PUBLIC_THEME=
|
||||
# NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=
|
||||
# NEXT_PUBLIC_CUSTOM_REFRESH_URL=
|
||||
|
||||
## Pointer to services
|
||||
|
||||
@@ -167,8 +167,6 @@ services:
|
||||
- NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=${NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED:-}
|
||||
# Enterprise Edition only
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
# DO NOT TURN ON unless you have EXPLICIT PERMISSION from Onyx.
|
||||
- NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
|
||||
- NODE_OPTIONS=${NODE_OPTIONS:-"--max-old-space-size=4096"}
|
||||
env_file:
|
||||
- path: .env
|
||||
|
||||
@@ -167,8 +167,6 @@ services:
|
||||
- NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=${NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED:-}
|
||||
# Enterprise Edition only
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
# DO NOT TURN ON unless you have EXPLICIT PERMISSION from Onyx.
|
||||
- NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
|
||||
- NODE_OPTIONS=${NODE_OPTIONS:-"--max-old-space-size=4096"}
|
||||
env_file:
|
||||
- path: .env
|
||||
|
||||
@@ -102,8 +102,6 @@ services:
|
||||
|
||||
# Enterprise Edition only
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
# DO NOT TURN ON unless you have EXPLICIT PERMISSION from Onyx.
|
||||
- NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
|
||||
depends_on:
|
||||
- api_server
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -251,8 +251,6 @@ services:
|
||||
- NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=${NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED:-}
|
||||
# Enterprise Edition only
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
# DO NOT TURN ON unless you have EXPLICIT PERMISSION from Onyx.
|
||||
- NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
|
||||
- NODE_OPTIONS=${NODE_OPTIONS:-"--max-old-space-size=4096"}
|
||||
env_file:
|
||||
- path: .env
|
||||
|
||||
@@ -208,8 +208,6 @@ services:
|
||||
- NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=${NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED:-}
|
||||
# Enterprise Edition only
|
||||
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
||||
# DO NOT TURN ON unless you have EXPLICIT PERMISSION from Onyx.
|
||||
- NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED:-false}
|
||||
- NODE_OPTIONS=${NODE_OPTIONS:-"--max-old-space-size=4096"}
|
||||
env_file:
|
||||
- path: .env
|
||||
|
||||
@@ -409,6 +409,8 @@ LOG_ONYX_MODEL_INTERACTIONS=False
|
||||
# SALESFORCE_CLIENT_SECRET=
|
||||
|
||||
## Miscellaneous
|
||||
# Hides "Powered by Onyx" on Enterprise. Do not set without explicit permission from Onyx.
|
||||
# HIDE_ONYX_BRANDING=
|
||||
# Kill switch for the gateway's native Anthropic passthrough (server tools,
|
||||
# thinking-block signatures, fine-grained streaming); default on. Set to false
|
||||
# to send Anthropic-backed providers back through the OpenAI-translation path.
|
||||
@@ -428,7 +430,6 @@ LOG_ONYX_MODEL_INTERACTIONS=False
|
||||
# NEXT_PUBLIC_DISABLE_LOGOUT=
|
||||
# NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=
|
||||
# NEXT_PUBLIC_THEME=
|
||||
# NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=
|
||||
# NEXT_PUBLIC_CUSTOM_REFRESH_URL=
|
||||
|
||||
## Pointer to services
|
||||
|
||||
@@ -51,9 +51,6 @@ ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ARG NEXT_PUBLIC_THEME
|
||||
ENV NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME}
|
||||
|
||||
ARG NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED
|
||||
ENV NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED}
|
||||
|
||||
ARG NEXT_PUBLIC_DISABLE_LOGOUT
|
||||
ENV NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT}
|
||||
|
||||
@@ -140,9 +137,6 @@ COPY --from=builder --chown=node:node /app/.next/static ./.next/static
|
||||
ARG NEXT_PUBLIC_THEME
|
||||
ENV NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME}
|
||||
|
||||
ARG NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED
|
||||
ENV NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED=${NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED}
|
||||
|
||||
ARG NEXT_PUBLIC_DISABLE_LOGOUT
|
||||
ENV NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT}
|
||||
|
||||
|
||||
@@ -581,36 +581,6 @@ export const AppearanceThemeSettings = forwardRef<
|
||||
</div>
|
||||
</Disabled>
|
||||
|
||||
<Disabled
|
||||
disabled={!enterpriseTier}
|
||||
tooltip={t("branding.enterpriseTooltip")}
|
||||
>
|
||||
<FormField state="idle" className="gap-0">
|
||||
<div className="flex justify-between items-center">
|
||||
<FormField.Label>
|
||||
{t("branding.label")}
|
||||
{!enterpriseTier && (
|
||||
<Tag {...planTagProps("enterprise")} size="sm" />
|
||||
)}
|
||||
</FormField.Label>
|
||||
<FormField.Control>
|
||||
<InputSwitch
|
||||
aria-label={t("branding.label")}
|
||||
data-label="hide-onyx-branding-toggle"
|
||||
checked={values.hide_onyx_branding}
|
||||
onCheckedChange={(checked) =>
|
||||
setFieldValue("hide_onyx_branding", checked)
|
||||
}
|
||||
disabled={!enterpriseTier}
|
||||
/>
|
||||
</FormField.Control>
|
||||
</div>
|
||||
<FormField.Description>
|
||||
{t("branding.description")}
|
||||
</FormField.Description>
|
||||
</FormField>
|
||||
</Disabled>
|
||||
|
||||
<Divider />
|
||||
|
||||
<div className="flex flex-col gap-4 p-4 bg-background-tint-00 rounded-16">
|
||||
|
||||
@@ -191,7 +191,6 @@ export default function ThemePage() {
|
||||
Yup.string().url().isValidSync(value)
|
||||
),
|
||||
}),
|
||||
hide_onyx_branding: Yup.boolean().nullable(),
|
||||
system_announcement_enabled: Yup.boolean().nullable(),
|
||||
system_announcement_header: Yup.string()
|
||||
.trim()
|
||||
@@ -245,7 +244,6 @@ export default function ThemePage() {
|
||||
custom_help_link_url: enterpriseSettings?.custom_help_link_url || "",
|
||||
custom_help_link_label:
|
||||
enterpriseSettings?.custom_help_link_label || "",
|
||||
hide_onyx_branding: enterpriseSettings?.hide_onyx_branding || false,
|
||||
system_announcement_enabled: !!currentBanner,
|
||||
system_announcement_header: currentBanner?.title || "",
|
||||
system_announcement_content: currentBanner?.content || "",
|
||||
@@ -298,7 +296,6 @@ export default function ThemePage() {
|
||||
consent_screen_prompt: values.consent_screen_prompt || null,
|
||||
custom_help_link_url: values.custom_help_link_url?.trim() || null,
|
||||
custom_help_link_label: values.custom_help_link_label?.trim() || null,
|
||||
hide_onyx_branding: values.hide_onyx_branding ?? null,
|
||||
});
|
||||
|
||||
// Only touch the banner after the settings save succeeds, and only when
|
||||
|
||||
@@ -7511,11 +7511,6 @@
|
||||
"description": "سيظهر هذا الاسم في جميع أنحاء التطبيق وسيحل محل \"Onyx\" في الواجهة.",
|
||||
"label": "اسم عرض التطبيق"
|
||||
},
|
||||
"branding": {
|
||||
"description": "أزل عبارة \"powered by Onyx\" وغيرها من عناصر علامة Onyx التجارية في التطبيق.",
|
||||
"enterpriseTooltip": "إخفاء علامة Onyx التجارية هو ميزة في خطة Enterprise.",
|
||||
"label": "إخفاء علامة Onyx التجارية"
|
||||
},
|
||||
"chatFooter": {
|
||||
"description": "أضف محتوى ماركداون لإخلاء المسؤولية أو معلومات إضافية.",
|
||||
"label": "نص تذييل الدردشة"
|
||||
|
||||
@@ -7511,11 +7511,6 @@
|
||||
"description": "Dieser Name wird in der gesamten App angezeigt und ersetzt \"Onyx\" in der Benutzeroberfläche.",
|
||||
"label": "Anzeigename der Anwendung"
|
||||
},
|
||||
"branding": {
|
||||
"description": "Entfernen Sie \"powered by Onyx\" und andere Onyx-Branding-Elemente in der App.",
|
||||
"enterpriseTooltip": "Das Ausblenden des Onyx-Brandings ist eine Funktion des Enterprise-Plans.",
|
||||
"label": "Onyx-Branding ausblenden"
|
||||
},
|
||||
"chatFooter": {
|
||||
"description": "Fügen Sie Markdown-Inhalte für Haftungsausschlüsse oder zusätzliche Informationen hinzu.",
|
||||
"label": "Text der Chat-Fußzeile"
|
||||
|
||||
@@ -7511,11 +7511,6 @@
|
||||
"description": "This name will show across the app and replace \"Onyx\" in the UI.",
|
||||
"label": "Application Display Name"
|
||||
},
|
||||
"branding": {
|
||||
"description": "Remove “powered by Onyx” and other Onyx branding presence in the app.",
|
||||
"enterpriseTooltip": "Hiding Onyx branding is an Enterprise Plan feature.",
|
||||
"label": "Hide Onyx Branding"
|
||||
},
|
||||
"chatFooter": {
|
||||
"description": "Add markdown content for disclaimers or additional information.",
|
||||
"label": "Chat Footer Text"
|
||||
|
||||
@@ -7511,11 +7511,6 @@
|
||||
"description": "Este nombre se mostrará en toda la aplicación y reemplazará a \"Onyx\" en la interfaz.",
|
||||
"label": "Nombre visible de la aplicación"
|
||||
},
|
||||
"branding": {
|
||||
"description": "Elimina \"powered by Onyx\" y otras menciones de la marca Onyx en la aplicación.",
|
||||
"enterpriseTooltip": "Ocultar la marca de Onyx es una función del plan Enterprise.",
|
||||
"label": "Ocultar la marca de Onyx"
|
||||
},
|
||||
"chatFooter": {
|
||||
"description": "Agrega contenido en markdown para avisos legales o información adicional.",
|
||||
"label": "Texto del pie del chat"
|
||||
|
||||
@@ -7511,11 +7511,6 @@
|
||||
"description": "Ce nom apparaîtra dans toute l'application et remplacera \"Onyx\" dans l'interface.",
|
||||
"label": "Nom d'affichage de l'application"
|
||||
},
|
||||
"branding": {
|
||||
"description": "Supprimez « powered by Onyx » et les autres présences de la marque Onyx dans l'application.",
|
||||
"enterpriseTooltip": "Masquer la marque Onyx est une fonctionnalité du forfait Enterprise.",
|
||||
"label": "Masquer la marque Onyx"
|
||||
},
|
||||
"chatFooter": {
|
||||
"description": "Ajoutez du contenu markdown pour des avertissements ou des informations supplémentaires.",
|
||||
"label": "Texte du pied de page du chat"
|
||||
|
||||
@@ -7511,11 +7511,6 @@
|
||||
"description": "この名前はアプリ全体に表示され、UI内の「Onyx」を置き換えます。",
|
||||
"label": "アプリケーションの表示名"
|
||||
},
|
||||
"branding": {
|
||||
"description": "アプリ内の「powered by Onyx」やその他のOnyxブランディングを削除します。",
|
||||
"enterpriseTooltip": "Onyxブランディングの非表示はEnterpriseプランの機能です。",
|
||||
"label": "Onyxブランディングを非表示"
|
||||
},
|
||||
"chatFooter": {
|
||||
"description": "免責事項や追加情報のためのマークダウンコンテンツを追加します。",
|
||||
"label": "チャットフッターのテキスト"
|
||||
|
||||
@@ -7511,11 +7511,6 @@
|
||||
"description": "이 이름은 앱 전체에 표시되며 UI에서 \"Onyx\"를 대체합니다.",
|
||||
"label": "애플리케이션 표시 이름"
|
||||
},
|
||||
"branding": {
|
||||
"description": "앱에서 \"powered by Onyx\" 및 기타 Onyx 브랜딩을 제거합니다.",
|
||||
"enterpriseTooltip": "Onyx 브랜딩 숨기기는 Enterprise 플랜 기능입니다.",
|
||||
"label": "Onyx 브랜딩 숨기기"
|
||||
},
|
||||
"chatFooter": {
|
||||
"description": "면책 조항이나 추가 정보를 위한 마크다운 콘텐츠를 추가하세요.",
|
||||
"label": "채팅 푸터 텍스트"
|
||||
|
||||
@@ -7511,11 +7511,6 @@
|
||||
"description": "Este nome aparecerá em todo o aplicativo e substituirá \"Onyx\" na interface.",
|
||||
"label": "Nome de exibição do aplicativo"
|
||||
},
|
||||
"branding": {
|
||||
"description": "Remova \"powered by Onyx\" e outras presenças da marca Onyx no aplicativo.",
|
||||
"enterpriseTooltip": "Ocultar a marca Onyx é um recurso do plano Enterprise.",
|
||||
"label": "Ocultar a marca Onyx"
|
||||
},
|
||||
"chatFooter": {
|
||||
"description": "Adicione conteúdo em markdown para avisos legais ou informações adicionais.",
|
||||
"label": "Texto do rodapé do chat"
|
||||
|
||||
@@ -7511,11 +7511,6 @@
|
||||
"description": "此名称将在整个应用中显示,并替换界面中的\"Onyx\"。",
|
||||
"label": "应用显示名称"
|
||||
},
|
||||
"branding": {
|
||||
"description": "移除应用中的\"powered by Onyx\"及其他 Onyx 品牌标识。",
|
||||
"enterpriseTooltip": "隐藏 Onyx 品牌标识是企业版套餐的功能。",
|
||||
"label": "隐藏 Onyx 品牌标识"
|
||||
},
|
||||
"chatFooter": {
|
||||
"description": "添加用于免责声明或附加信息的 markdown 内容。",
|
||||
"label": "聊天页脚文本"
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useSettings } from "@/lib/settings/hooks";
|
||||
import {
|
||||
DEFAULT_LOGO_SIZE_PX,
|
||||
NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED,
|
||||
} from "@/lib/constants";
|
||||
import { DEFAULT_LOGO_SIZE_PX } from "@/lib/constants";
|
||||
import { cn } from "@opal/utils";
|
||||
import Text from "@/refresh-components/texts/Text";
|
||||
import Truncated from "@/refresh-components/texts/Truncated";
|
||||
@@ -72,7 +69,7 @@ export function FoldableLogo({
|
||||
}: FoldableLogoProps) {
|
||||
const t = useTranslations("common");
|
||||
const resolvedSize = size ?? DEFAULT_LOGO_SIZE_PX;
|
||||
const { enterprise } = useSettings();
|
||||
const { enterprise, hide_onyx_branding, isLoading } = useSettings();
|
||||
const logoDisplayStyle = enterprise?.logo_display_style;
|
||||
const applicationName = enterprise?.application_name;
|
||||
|
||||
@@ -99,17 +96,17 @@ export function FoldableLogo({
|
||||
{opts.includeName && (
|
||||
<Truncated headingH3>{applicationName}</Truncated>
|
||||
)}
|
||||
{!NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED &&
|
||||
!enterprise?.hide_onyx_branding && (
|
||||
<Text
|
||||
secondaryBody
|
||||
text03
|
||||
className={"line-clamp-1 truncate"}
|
||||
nowrap
|
||||
>
|
||||
{t("logo.poweredBy.label")}
|
||||
</Text>
|
||||
)}
|
||||
{/* Wait for settings so a hidden tagline never flashes. */}
|
||||
{!isLoading && !hide_onyx_branding && (
|
||||
<Text
|
||||
secondaryBody
|
||||
text03
|
||||
className={"line-clamp-1 truncate"}
|
||||
nowrap
|
||||
>
|
||||
{t("logo.poweredBy.label")}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -11,10 +11,6 @@ export const DOCS_ADMINS_PATH = `${DOCS_BASE_URL}/admins`;
|
||||
export const MCP_INTERNAL_URL =
|
||||
process.env.MCP_INTERNAL_URL || "http://127.0.0.1:8090";
|
||||
|
||||
export const NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED =
|
||||
process.env.NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED?.toLowerCase() ===
|
||||
"true";
|
||||
|
||||
// Name of the FastAPI-Users auth cookie. Configurable via env (shared with the
|
||||
// backend's AUTH_COOKIE_NAME) so deployments sharing a hostname — e.g. parallel
|
||||
// local worktrees on different ports of localhost — keep separate auth cookies.
|
||||
|
||||
@@ -97,6 +97,9 @@ export interface Settings {
|
||||
// are unavailable.
|
||||
vector_db_enabled?: boolean;
|
||||
|
||||
// HIDE_ONYX_BRANDING env var, honored only on the Enterprise tier.
|
||||
hide_onyx_branding?: boolean;
|
||||
|
||||
// True when hooks are available: single-tenant deployments only.
|
||||
hooks_enabled?: boolean;
|
||||
|
||||
@@ -150,9 +153,6 @@ export interface EnterpriseSettings {
|
||||
// Custom help link surfaced in the profile dropdown alongside "Help & FAQ".
|
||||
custom_help_link_url: string | null;
|
||||
custom_help_link_label: string | null;
|
||||
|
||||
// Hide the "Powered by Onyx" tagline under the sidebar logo.
|
||||
hide_onyx_branding: boolean | null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Page Object Model for the Admin Appearance / Theme page (/admin/theme).
|
||||
*
|
||||
* Encapsulates locators and interactions for the custom help link and
|
||||
* hide-onyx-branding controls so specs stay declarative. Existing tests in
|
||||
* "Powered by Onyx" tagline so specs stay declarative. Existing tests in
|
||||
* `appearance_theme_settings.spec.ts` still use inline locators; new tests
|
||||
* should drive the page through this class.
|
||||
*/
|
||||
@@ -37,7 +37,6 @@ export class AppearanceThemePage {
|
||||
readonly applicationNameInput: Locator;
|
||||
readonly customHelpLinkUrlInput: Locator;
|
||||
readonly customHelpLinkLabelInput: Locator;
|
||||
readonly hideBrandingToggle: Locator;
|
||||
readonly saveButton: Locator;
|
||||
|
||||
// Sidebar / popover
|
||||
@@ -54,9 +53,6 @@ export class AppearanceThemePage {
|
||||
this.customHelpLinkLabelInput = page.locator(
|
||||
'[data-label="custom-help-link-label-input"]'
|
||||
);
|
||||
this.hideBrandingToggle = page.locator(
|
||||
'[data-label="hide-onyx-branding-toggle"]'
|
||||
);
|
||||
this.saveButton = page.getByRole("button", { name: "Apply Changes" });
|
||||
|
||||
this.userDropdownTrigger = page.locator("#onyx-user-dropdown");
|
||||
@@ -96,11 +92,6 @@ export class AppearanceThemePage {
|
||||
await this.customHelpLinkLabelInput.clear();
|
||||
}
|
||||
|
||||
async toggleHideBranding() {
|
||||
await this.hideBrandingToggle.scrollIntoViewIfNeeded();
|
||||
await this.hideBrandingToggle.click();
|
||||
}
|
||||
|
||||
/**
|
||||
* Click "Apply Changes" and wait for both the PUT and the subsequent SWR
|
||||
* revalidation GET. Both promises MUST be armed before the click — a
|
||||
@@ -165,23 +156,10 @@ export class AppearanceThemePage {
|
||||
await expect(link).toContainText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locator for the Logo's tagline, scoped exactly so it doesn't also match
|
||||
* the toggle's helper text on the same page ("Remove 'powered by Onyx'
|
||||
* and other Onyx branding..."). `getByText` is case-insensitive +
|
||||
* substring by default; `exact: true` makes it strict equality on the
|
||||
* element's full text content.
|
||||
*/
|
||||
private get poweredByOnyxTagline(): Locator {
|
||||
return this.page.getByText("Powered by Onyx", { exact: true });
|
||||
}
|
||||
|
||||
async expectPoweredByOnyxVisible() {
|
||||
await expect(this.poweredByOnyxTagline).toBeVisible({ timeout: 5_000 });
|
||||
}
|
||||
|
||||
async expectPoweredByOnyxAbsent() {
|
||||
await expect(this.poweredByOnyxTagline).toHaveCount(0, { timeout: 5_000 });
|
||||
await expect(
|
||||
this.page.getByText("Powered by Onyx", { exact: true })
|
||||
).toBeVisible({ timeout: 5_000 });
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -89,21 +89,6 @@ test.describe("Appearance Theme Settings @exclusive", () => {
|
||||
await helpLinkLabelInput.clear();
|
||||
}
|
||||
|
||||
// Disable hide-onyx-branding toggle if enabled
|
||||
const hideBrandingToggle = page.locator(
|
||||
'[data-label="hide-onyx-branding-toggle"]'
|
||||
);
|
||||
if (
|
||||
await hideBrandingToggle.isVisible({ timeout: 1000 }).catch(() => false)
|
||||
) {
|
||||
const hideBrandingState =
|
||||
await hideBrandingToggle.getAttribute("aria-checked");
|
||||
if (hideBrandingState === "true") {
|
||||
await hideBrandingToggle.click();
|
||||
await page.waitForTimeout(300);
|
||||
}
|
||||
}
|
||||
|
||||
// Save reset. Arm the PUT waiter *before* clicking — a post-click
|
||||
// waitForResponse can miss a fast response and then hang until the test
|
||||
// timeout (the whole point of saveAndWaitForPut in AppearanceThemePage).
|
||||
@@ -313,32 +298,25 @@ test.describe("Appearance Theme Settings @exclusive", () => {
|
||||
await themePage.clearCustomHelpLinkLabel();
|
||||
});
|
||||
|
||||
test("Hide Onyx Branding toggle removes the 'Powered by Onyx' tagline", async ({
|
||||
test("custom application name keeps the 'Powered by Onyx' tagline", async ({
|
||||
page,
|
||||
}) => {
|
||||
const settings = await (await page.request.get("/api/settings")).json();
|
||||
test.skip(
|
||||
settings.hide_onyx_branding === true,
|
||||
"HIDE_ONYX_BRANDING hides the tagline on this deployment"
|
||||
);
|
||||
|
||||
const themePage = new AppearanceThemePage(page);
|
||||
|
||||
// The sidebar's "Powered by Onyx" tagline only renders alongside an
|
||||
// application name (the Logo's logo_and_name fall-through path), so
|
||||
// first set a name and save a baseline that we can then assert against.
|
||||
// With the default display style, the tagline renders only when an
|
||||
// application name is set.
|
||||
await themePage.setApplicationName(TEST_VALUES.applicationName);
|
||||
const baselineResponse = await themePage.saveAndWaitForPut();
|
||||
expect(baselineResponse.status()).toBe(200);
|
||||
await themePage.expectSaveSuccessToast();
|
||||
await themePage.reloadAndWaitForForm();
|
||||
|
||||
// Sanity: tagline now visible alongside the application name
|
||||
await themePage.expectPoweredByOnyxVisible();
|
||||
|
||||
await themePage.toggleHideBranding();
|
||||
|
||||
const response = await themePage.saveAndWaitForPut();
|
||||
expect(response.status()).toBe(200);
|
||||
await themePage.expectSaveSuccessToast();
|
||||
|
||||
// Reload to read the persisted setting fresh — the sidebar then re-
|
||||
// renders the Logo without the tagline.
|
||||
await themePage.reloadAndWaitForForm();
|
||||
await themePage.expectPoweredByOnyxAbsent();
|
||||
|
||||
await themePage.expectPoweredByOnyxVisible();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user