fix(desktop): scope account access to owning client and extend identity verification
Backend CI / Backend (push) Successful in 14m18s
Backend CI / Backend (push) Successful in 14m18s
Restrict account tracking, probing, and health reporting to accounts owned by the current client (client_id match). Extend identity-match verification to bilibili, juejin, and smzdm so session validity is confirmed locally rather than deferred to remote health state. Server-side account view now uses stored client_id as authoritative owner instead of presence data. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ import {
|
||||
forgetTrackedAccountHealth,
|
||||
getAccountHealthSnapshot,
|
||||
getProjectedAccountHealth,
|
||||
markTrackedAccountMissingPartition,
|
||||
markTrackedAccountBound,
|
||||
probeTrackedAccount,
|
||||
reconcileTrackedAccountRemoteState,
|
||||
@@ -319,8 +320,24 @@ function hasLocalAccountSession(accountId: string): boolean {
|
||||
return Boolean(getSessionHandle(accountId) || getPersistedPartition(accountId))
|
||||
}
|
||||
|
||||
function isAccountOwnedByCurrentClient(account: DesktopAccountInfo): boolean {
|
||||
return Boolean(account.client_id && account.client_id === state.client?.id)
|
||||
}
|
||||
|
||||
function hasLocalAccountAuthorization(account: DesktopAccountInfo): boolean {
|
||||
return isAccountOwnedByCurrentClient(account)
|
||||
}
|
||||
|
||||
function accountRequiresLocalAuthorization(account: DesktopAccountInfo): boolean {
|
||||
return Boolean(account.client_id)
|
||||
}
|
||||
|
||||
function accountRequiresStrictProbe(account: DesktopAccountInfo): boolean {
|
||||
return ['bilibili', 'juejin', 'smzdm'].includes(account.platform)
|
||||
}
|
||||
|
||||
function shouldReportAccountPresence(account: DesktopAccountInfo): boolean {
|
||||
return hasLocalAccountSession(account.id) || account.client_id === state.client?.id
|
||||
return hasLocalAccountSession(account.id) && isAccountOwnedByCurrentClient(account)
|
||||
}
|
||||
|
||||
function runtimePlatformLabel(platform: string): string {
|
||||
@@ -955,7 +972,9 @@ async function syncAccounts(source: 'startup' | 'manual'): Promise<void> {
|
||||
noteSchedulerAccountsSync()
|
||||
setSchedulerError(null)
|
||||
|
||||
const identities = accounts.map((account) => accountIdentityFromDesktopAccount(account))
|
||||
const identities = accounts
|
||||
.filter((account) => hasLocalAccountAuthorization(account))
|
||||
.map((account) => accountIdentityFromDesktopAccount(account))
|
||||
syncTrackedAccounts(identities)
|
||||
state.accountRemoteHealth = new Map(accounts.map((account) => [account.id, account.health]))
|
||||
|
||||
@@ -968,15 +987,19 @@ async function syncAccounts(source: 'startup' | 'manual'): Promise<void> {
|
||||
...account,
|
||||
platform_uid: normalizedPlatformUid,
|
||||
})
|
||||
reconcileTrackedAccountRemoteState(accountIdentity, {
|
||||
health: account.health,
|
||||
verifiedAt: account.verified_at,
|
||||
profile: {
|
||||
subjectUid: normalizedPlatformUid,
|
||||
displayName: account.display_name,
|
||||
avatarUrl: account.avatar_url,
|
||||
},
|
||||
})
|
||||
if (hasLocalAccountAuthorization(account) && !accountRequiresStrictProbe(account)) {
|
||||
reconcileTrackedAccountRemoteState(accountIdentity, {
|
||||
health: account.health,
|
||||
verifiedAt: account.verified_at,
|
||||
profile: {
|
||||
subjectUid: normalizedPlatformUid,
|
||||
displayName: account.display_name,
|
||||
avatarUrl: account.avatar_url,
|
||||
},
|
||||
})
|
||||
} else if (accountRequiresLocalAuthorization(account)) {
|
||||
markTrackedAccountMissingPartition(accountIdentity)
|
||||
}
|
||||
const projected = getProjectedAccountHealth({
|
||||
accountId: account.id,
|
||||
platform: account.platform,
|
||||
@@ -1140,6 +1163,9 @@ function enqueueAccountHealthReport(accountId: string): void {
|
||||
if (!account) {
|
||||
return
|
||||
}
|
||||
if (!hasLocalAccountAuthorization(account)) {
|
||||
return
|
||||
}
|
||||
|
||||
const report = buildAccountHealthReport(account)
|
||||
if (!shouldQueueAccountHealthReport(account, report)) {
|
||||
@@ -1270,6 +1296,10 @@ export async function requestRuntimeAccountProbe(
|
||||
if (!account) {
|
||||
throw new Error('runtime_account_not_found')
|
||||
}
|
||||
if (existingAccount && !hasLocalAccountAuthorization(existingAccount)) {
|
||||
markTrackedAccountMissingPartition(account)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await probeTrackedAccount(account, {
|
||||
@@ -1318,7 +1348,11 @@ export function noteRuntimeAccountBound(account: DesktopAccountInfo): void {
|
||||
avatarUrl: normalizedAccount.avatar_url,
|
||||
})
|
||||
state.lastAccountsSyncAt = Date.now()
|
||||
syncTrackedAccounts(state.accounts.map((item) => accountIdentityFromDesktopAccount(item)))
|
||||
syncTrackedAccounts(
|
||||
state.accounts
|
||||
.filter((item) => hasLocalAccountAuthorization(item))
|
||||
.map((item) => accountIdentityFromDesktopAccount(item)),
|
||||
)
|
||||
markTrackedAccountBound(accountIdentityFromDesktopAccount(normalizedAccount), {
|
||||
subjectUid: normalizedAccount.platform_uid,
|
||||
displayName: normalizedAccount.display_name,
|
||||
|
||||
Reference in New Issue
Block a user