Repository navigation
fix: knowledge workflow permission - #7758
Conversation
| <MkDropdownItem v-if="knowledgeWorkflowPermission('workflowEdit')" @click.stop> | ||
| <template #icon><MkIcon name="icon_save_outlined" /></template> | ||
| <span>自动保存</span> | ||
| <el-switch v-model="autoSaveEnabled" class="ml-auto" size="small" @click.stop @change="handleAutoSaveChange" /> |
There was a problem hiding this comment.
Based on the shown diff, the change is generally reasonable, but there are several important issues to address before merging.
Critical issues
1. UI hiding is not authorization
Using v-if="knowledgeWorkflowPermission(...)" only hides controls. The handlers are still callable via keyboard shortcuts, programmatic calls, or other UI paths:
handleSavehandleOpenPublishhandleExportWorkflowhandleAutoSaveChange
Add permission checks inside the handlers as well. Server-side authorization must also enforce these rules.
function handleSave() {
if (!knowledgeWorkflowPermission('workflowEdit')) return
// ...
}
function handleOpenPublish() {
if (!knowledgeWorkflowPermission('publish')) return
// ...
}
function handleExportWorkflow() {
if (!knowledgeWorkflowPermission('workflowExport')) return
// ...
}2. Auto-save may continue running after permission is lost
You hide the auto-save switch, but if autoSaveEnabled was already true, the auto-save logic may continue saving. This is especially risky for shared/read-only resources.
You should stop auto-save when edit permission becomes unavailable:
watch(
() => knowledgeWorkflowPermission('workflowEdit'),
(canEdit) => {
if (!canEdit) {
autoSaveEnabled.value = false
stopAutoSave()
}
},
{ immediate: true }
)Also guard handleAutoSaveChange and the auto-save execution path.
3. Verify knowledgeId is not a ref/computed
The helper uses:
perm.knowledge.workspace[method](knowledgeId)If knowledgeId is a ref or computed, this passes a Ref object instead of the actual ID. In that case, use:
perm.knowledge.workspace[method](knowledgeId.value)The same applies if isSystemResource, isSystemSharedResource, or isWorkspaceSharedResource are computed values rather than functions.
Potential behavioral issue
4. Workspace-shared resources always return false
This line:
if (isWorkspaceSharedResource()) return false // 工作空间侧共享知识库只读blocks all three permissions, including workflowExport. If export is intended to be allowed for read-only shared resources, this is too restrictive. Confirm whether workflowExport should really be blocked here.
Minor improvements
5. Avoid repeated permission calls in the template
knowledgeWorkflowPermission(...) is called multiple times per render. Prefer computed properties:
const canEditWorkflow = computed(() => knowledgeWorkflowPermission('workflowEdit'))
const canPublish = computed(() => knowledgeWorkflowPermission('publish'))
const canExportWorkflow = computed(() => knowledgeWorkflowPermission('workflowExport'))Then use:
<MkTooltip v-if="canEditWorkflow" ...>This improves readability, avoids repeated permission logic, and makes watchers/guards easier.
6. Prefer extensionless import
This:
import perm from '@/permission/index.ts'may work in Vite, but extensionless imports are more conventional and avoid TypeScript/bundler configuration issues:
import perm from '@/permission'7. Consider a guard for missing permission methods
If perm is not fully typed or can change between versions, a missing method will throw:
perm.knowledge.workspace[method](knowledgeId)You could defensively check:
const check = perm.knowledge.workspace[method]
return typeof check === 'function' ? Boolean(check(knowledgeId)) : falseOnly do this if perm is not strongly typed.
Suggested refactor
import perm from '@/permission'
type KnowledgeWorkflowPermissionMethod =
| 'workflowEdit'
| 'publish'
| 'workflowExport'
function knowledgeWorkflowPermission(
method: KnowledgeWorkflowPermissionMethod
): boolean {
if (isSystemResource()) {
return Boolean(perm.knowledge.system[method]())
}
if (isSystemSharedResource()) {
return Boolean(perm.knowledge.share[method]())
}
if (isWorkspaceSharedResource()) {
return false
}
// Use knowledgeId.value if knowledgeId is a ref/computed
return Boolean(perm.knowledge.workspace[method](knowledgeId))
}
const canEditWorkflow = computed(() => knowledgeWorkflowPermission('workflowEdit'))
const canPublish = computed(() => knowledgeWorkflowPermission('publish'))
const canExportWorkflow = computed(() => knowledgeWorkflowPermission('workflowExport'))Overall: the diff is syntactically plausible, but the main missing piece is enforcing the same permission checks in the action handlers and auto-save lifecycle, not only in the template.
fix: knowledge workflow permission