fix: archived logs only saas and admin can view

This commit is contained in:
hjlarry
2026-06-30 16:48:47 +08:00
parent add719a6e1
commit fde2042cfe
4 changed files with 84 additions and 1 deletions

View File

@ -33,6 +33,20 @@ vi.mock('@/next/navigation', () => ({
}),
}))
vi.mock('@/config', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/config')>()
return {
...actual,
IS_CLOUD_EDITION: true,
}
})
vi.mock('@/context/app-context', () => ({
useAppContext: () => ({
isCurrentWorkspaceManager: true,
}),
}))
vi.mock('@/context/i18n', () => ({
useDocLink: () => (path: string) => `https://docs.example.com${path}`,
}))

View File

@ -2,12 +2,18 @@
import { useTranslation } from 'react-i18next'
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
import { IS_CLOUD_EDITION } from '@/config'
import { useAppContext } from '@/context/app-context'
import { useModalContextSelector } from '@/context/modal-context'
export function ArchivedLogsNotice() {
const { t } = useTranslation()
const { isCurrentWorkspaceManager } = useAppContext()
const setShowAccountSettingModal = useModalContextSelector(state => state.setShowAccountSettingModal)
if (!IS_CLOUD_EDITION || !isCurrentWorkspaceManager)
return null
return (
<div className="mb-3 flex items-start gap-2 rounded-lg border border-util-colors-warning-warning-200 bg-util-colors-warning-warning-50 px-3 py-2">
<span aria-hidden className="mt-0.5 i-ri-information-line size-4 shrink-0 text-util-colors-warning-warning-600" />

View File

@ -10,10 +10,23 @@ import { ACCOUNT_SETTING_TAB } from '../constants'
import AccountSetting from '../index'
const mockResetModelProviderListExpanded = vi.fn()
const mockConfig = vi.hoisted(() => ({
IS_CLOUD_EDITION: true,
}))
const mockAppContextState = vi.hoisted(() => ({
current: null as unknown,
}))
vi.mock('@/config', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/config')>()
return {
...actual,
get IS_CLOUD_EDITION() {
return mockConfig.IS_CLOUD_EDITION
},
}
})
vi.mock('@/context/provider-context', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/context/provider-context')>()
return {
@ -220,6 +233,7 @@ describe('AccountSetting', () => {
beforeEach(() => {
vi.clearAllMocks()
mockConfig.IS_CLOUD_EDITION = true
vi.mocked(useProviderContext).mockReturnValue({
...baseProviderContextValue,
enableBilling: true,
@ -505,6 +519,54 @@ describe('AccountSetting', () => {
expect(screen.queryByRole('button', { name: 'common.settings.billing' })).not.toBeInTheDocument()
})
it('should hide workflow log archives outside cloud edition', () => {
// Arrange
mockConfig.IS_CLOUD_EDITION = false
// Act
renderAccountSetting()
// Assert
expect(screen.queryByRole('button', { name: 'appLog.archives.title' })).not.toBeInTheDocument()
})
it('should hide workflow log archives from custom RBAC roles that are not owner or admin', () => {
// Arrange
const contextWithRoleManagePermissionButNotManager = {
...baseAppContextValue,
currentWorkspace: {
...baseAppContextValue.currentWorkspace,
role: 'normal' as const,
},
isCurrentWorkspaceManager: false,
isCurrentWorkspaceOwner: false,
workspacePermissionKeys: [
...baseAppContextValue.workspacePermissionKeys,
'workspace.role.manage',
],
}
vi.mocked(useAppContext).mockReturnValue(contextWithRoleManagePermissionButNotManager)
mockAppContextState.current = contextWithRoleManagePermissionButNotManager
// Act
renderAccountSetting()
// Assert
expect(screen.queryByRole('button', { name: 'appLog.archives.title' })).not.toBeInTheDocument()
})
it('should not render workflow log archives page outside cloud edition', () => {
// Arrange
mockConfig.IS_CLOUD_EDITION = false
// Act
renderAccountSetting({ initialTab: ACCOUNT_SETTING_TAB.WORKFLOW_LOG_ARCHIVES })
// Assert
expect(screen.queryByTestId('workflow-log-archives-page')).not.toBeInTheDocument()
expect(screen.getAllByText('common.settings.members').length).toBeGreaterThan(0)
})
it('should not render billing page when active billing tab lacks billing view permission', () => {
// Arrange
const contextWithoutBillingViewPermission = {

View File

@ -12,6 +12,7 @@ import {
ACCOUNT_SETTING_TAB,
} from '@/app/components/header/account-setting/constants'
import MenuDialog from '@/app/components/header/account-setting/menu-dialog'
import { IS_CLOUD_EDITION } from '@/config'
import { useAppContext } from '@/context/app-context'
import { useProviderContext } from '@/context/provider-context'
import { systemFeaturesQueryOptions } from '@/features/system-features/client'
@ -59,7 +60,7 @@ export default function AccountSetting({
const isRbacEnabled = systemFeatures.rbac_enabled
const canManageWorkspaceRoles = isRbacEnabled && hasPermission(workspacePermissionKeys, 'workspace.role.manage')
const canViewBilling = enableBilling && hasPermission(workspacePermissionKeys, BillingPermission.View)
const canViewWorkflowLogArchives = isCurrentWorkspaceManager || canManageWorkspaceRoles
const canViewWorkflowLogArchives = IS_CLOUD_EDITION && isCurrentWorkspaceManager
// Keep legacy `language` deep links opening Preferences during the tab rename migration.
const normalizedActiveTab = activeTab === ACCOUNT_SETTING_TAB.LANGUAGE ? ACCOUNT_SETTING_TAB.PREFERENCES : activeTab
const activeMenu = (() => {