feat(auth): clear tenant-scoped client state on tenant change

Implemented a new function to clear tenant-specific data from localStorage when a user switches tenants. This prevents issues with stale data being used in the new tenant context, which could lead to backend errors. The function is called during the tenant selection process to ensure a clean state for the new tenant.

Refs: #1303
This commit is contained in:
wizardchen
2026-05-17 00:29:48 +08:00
committed by lyingbug
parent 3693f977ab
commit df74fa239b
3 changed files with 926 additions and 1318 deletions

View File

@@ -6,6 +6,7 @@ import i18n from '@/i18n'
import { reloadFontFromStorage } from '@/composables/useFont'
import { reloadThemeFromStorage } from '@/composables/useTheme'
import { resetMigrationLatch } from '@/composables/preferenceStorage'
import { BUILTIN_QUICK_ANSWER_ID } from '@/api/agent'
// Per-user UI preferences are namespaced by user id in localStorage.
// Reload them whenever the active user changes.
@@ -175,7 +176,43 @@ export const useAuthStore = defineStore('auth', () => {
}
}
// Wipe chat / KB selections that were saved under the previous tenant.
// These keys are NOT tenant-scoped in storage; after a tenant switch they
// would otherwise be reloaded verbatim and the chat input would post under
// the new tenant with an Agent / model id that only existed in the old
// tenant — backend 403s or "model not found". Called from setSelectedTenant
// only on an actual tenant change, so logout / init paths are not touched.
const clearTenantScopedClientState = () => {
try {
localStorage.removeItem('weknora_last_chat_model_id')
localStorage.removeItem('weknora_current_kb')
const raw = localStorage.getItem('WeKnora_settings')
if (raw) {
const parsed = JSON.parse(raw)
if (parsed && typeof parsed === 'object') {
parsed.selectedAgentId = BUILTIN_QUICK_ANSWER_ID
parsed.selectedAgentSourceTenantId = null
if (parsed.conversationModels && typeof parsed.conversationModels === 'object') {
parsed.conversationModels.summaryModelId = ''
parsed.conversationModels.rerankModelId = ''
parsed.conversationModels.selectedChatModelId = ''
}
parsed.selectedKnowledgeBases = []
parsed.selectedFiles = []
parsed.selectedFileKbMap = {}
parsed.knowledgeBaseId = ''
localStorage.setItem('WeKnora_settings', JSON.stringify(parsed))
}
}
} catch (e) {
// localStorage may be disabled or contain malformed JSON — best effort.
console.warn('[auth] failed to clear tenant-scoped client state', e)
}
}
const setSelectedTenant = (tenantId: number | null, tenantName: string | null = null) => {
const previousTenantId = selectedTenantId.value
const tenantChanged = previousTenantId !== tenantId
selectedTenantId.value = tenantId
selectedTenantName.value = tenantName
if (tenantId !== null) {
@@ -187,6 +224,9 @@ export const useAuthStore = defineStore('auth', () => {
localStorage.removeItem('weknora_selected_tenant_id')
localStorage.removeItem('weknora_selected_tenant_name')
}
if (tenantChanged) {
clearTenantScopedClientState()
}
}
const setAllTenants = (tenants: TenantInfoFromAPI[]) => {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff