新增: 信任所有目录扩展至敏感目录放行
开关语义升级为完全放行,含 .ssh/.aws 等黑名单目录(产品拍板体验优先,用户知情选择) validate_path 与 is_authorized 双拦截点经进程级标志同源放行,audit 层每轮工具执行前刷新 设置页开启时二次确认,正文明示敏感凭据可进对话上下文风险自担;对话区常驻放行横幅既有 测试以串行闸防并行互踩进程级标志
This commit is contained in:
@@ -8,11 +8,14 @@
|
||||
<!-- 说明 -->
|
||||
<p class="allowed-dirs-desc">{{ $t('settings.descAllowedDirs') }}</p>
|
||||
|
||||
<!-- 「信任所有目录」总开关:开启后白名单外路径不再逐次弹授权(后端黑名单仍硬拒)。
|
||||
走 appSettings KV(df-ai-path-auth-bypass),后端 process_tool_calls 每轮读取,改后即时生效。 -->
|
||||
<!-- 「信任所有目录」总开关:开启后白名单外路径不再逐次弹授权(后端黑名单拦截同步放行)。
|
||||
走 appSettings KV(df-ai-path-auth-bypass),后端 process_tool_calls 每轮读取,改后即时生效。
|
||||
开启方向二次确认(全放敏感目录须确认+风险自担):checked 单向绑定 + @change 裁决,
|
||||
确认前不写 ref。若 v-model 直写,弹窗期间 useSetting 的 debounced 落库已把 true 推给后端,
|
||||
取消也收不回这段已放行窗口。 -->
|
||||
<SettingRow :label="$t('settings.labelPathAuthBypass')" :desc="$t('settings.descPathAuthBypass')">
|
||||
<label class="toggle">
|
||||
<input type="checkbox" v-model="pathAuthBypass" />
|
||||
<input type="checkbox" :checked="pathAuthBypass" @change="onPathAuthBypassChange" />
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</SettingRow>
|
||||
@@ -82,6 +85,20 @@
|
||||
<p class="script-safety-note">{{ $t('settings.noteScriptSafety') }}</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 「信任所有目录」二次确认弹层(同 AdvancedSection 的 all 接管确认:自渲染独立弹层,
|
||||
msg 拼标题+正文,confirm-msg 用 pre-line 保留换行) -->
|
||||
<Transition name="confirm">
|
||||
<div v-if="confirmState.visible" class="confirm-mask" @click.self="answerConfirm(false)">
|
||||
<div class="confirm-box">
|
||||
<div class="confirm-msg">{{ confirmState.msg }}</div>
|
||||
<div class="confirm-actions">
|
||||
<button class="btn btn-ghost btn-sm" @click="answerConfirm(false)">{{ $t('common.cancel') }}</button>
|
||||
<button class="btn btn-danger btn-sm" @click="answerConfirm(true)">{{ confirmState.dangerLabel || $t('common.confirm') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -91,6 +108,7 @@ import { useI18n } from 'vue-i18n'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { aiApi, settingsApi } from '@/api'
|
||||
import { useAppSettingsStore } from '@/stores/appSettings'
|
||||
import { useConfirm } from '@/composables/useConfirm'
|
||||
import SettingRow from './SettingRow.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
@@ -111,6 +129,24 @@ const saving = ref(false)
|
||||
// 「信任所有目录」总开关(useSetting 双向绑 KV,写走 debounced 落库,后端每轮工具执行前读)
|
||||
const pathAuthBypass = appSettings.useSetting<boolean>('df-ai-path-auth-bypass', false)
|
||||
|
||||
// useConfirm 真实 API:返回 { confirmState, confirmDialog(msg, dangerLabel), answerConfirm(ok) },
|
||||
// confirmDialog 返回 Promise<boolean>(true=确认),弹层 UI 在本组件模板尾部自渲染。
|
||||
const { confirmState, confirmDialog, answerConfirm } = useConfirm()
|
||||
|
||||
// 开启方向(false→true)二次确认:确认才落 true,取消仅回弹。关闭方向不拦截直接落。
|
||||
async function onPathAuthBypassChange(e: Event) {
|
||||
const input = e.target as HTMLInputElement
|
||||
if (!input.checked) {
|
||||
pathAuthBypass.value = false
|
||||
return
|
||||
}
|
||||
input.checked = false
|
||||
const msg = t('settings.pathAuthBypassConfirmTitle') + '\n\n' + t('settings.pathAuthBypassConfirmBody')
|
||||
if (await confirmDialog(msg, t('common.confirm'))) {
|
||||
pathAuthBypass.value = true
|
||||
}
|
||||
}
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
@@ -262,4 +298,30 @@ onMounted(load)
|
||||
.script-safety-note {
|
||||
font-size: 11px; color: var(--df-text-dim); margin: 4px 0 0; line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 「信任所有目录」二次确认弹层(同 AdvancedSection) */
|
||||
.confirm-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 1100;
|
||||
background: rgba(0,0,0,0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.confirm-box {
|
||||
background: var(--df-bg-card);
|
||||
border: 0.5px solid var(--df-border);
|
||||
border-radius: var(--df-radius-lg);
|
||||
padding: 20px;
|
||||
min-width: 280px;
|
||||
max-width: 420px;
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
||||
}
|
||||
.confirm-msg { font-size: 13px; color: var(--df-text); line-height: 1.5; margin-bottom: 16px; white-space: pre-line; }
|
||||
.confirm-actions { display: flex; justify-content: flex-end; gap: 8px; }
|
||||
.btn-danger { background: var(--df-danger); color: #fff; }
|
||||
.btn-danger:hover { filter: brightness(1.1); }
|
||||
.confirm-enter-active, .confirm-leave-active { transition: opacity 0.15s; }
|
||||
.confirm-enter-from, .confirm-leave-to { opacity: 0; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user