重构git凭证托管,改为操作系统托管
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog"
|
||||
import { saveAccountToken } from "@/lib/tauri"
|
||||
import type { GitHubAccount } from "@/lib/types"
|
||||
|
||||
interface AddGitAccountDialogProps {
|
||||
@@ -52,7 +53,7 @@ export function AddGitAccountDialog({
|
||||
[onOpenChange, resetForm]
|
||||
)
|
||||
|
||||
const handleSubmit = useCallback(() => {
|
||||
const handleSubmit = useCallback(async () => {
|
||||
const trimmedUrl = serverUrl.trim()
|
||||
const trimmedUser = username.trim()
|
||||
const trimmedPass = password.trim()
|
||||
@@ -74,13 +75,19 @@ export function AddGitAccountDialog({
|
||||
id: crypto.randomUUID(),
|
||||
server_url: trimmedUrl,
|
||||
username: trimmedUser,
|
||||
token: trimmedPass,
|
||||
scopes: [],
|
||||
avatar_url: null,
|
||||
is_default: isFirstAccount,
|
||||
created_at: new Date().toISOString(),
|
||||
}
|
||||
|
||||
try {
|
||||
await saveAccountToken(account.id, trimmedPass)
|
||||
} catch {
|
||||
setError(t("gitAccount.passwordRequired"))
|
||||
return
|
||||
}
|
||||
|
||||
onAccountAdded(account)
|
||||
handleOpenChange(false)
|
||||
}, [
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog"
|
||||
import { validateGitHubToken } from "@/lib/tauri"
|
||||
import { validateGitHubToken, saveAccountToken } from "@/lib/tauri"
|
||||
import type { GitHubAccount } from "@/lib/types"
|
||||
|
||||
interface AddGitHubAccountDialogProps {
|
||||
@@ -94,13 +94,13 @@ export function AddGitHubAccountDialog({
|
||||
id: crypto.randomUUID(),
|
||||
server_url: serverUrl.trim() || "https://github.com",
|
||||
username: result.username ?? "unknown",
|
||||
token: trimmedToken,
|
||||
scopes: result.scopes,
|
||||
avatar_url: result.avatar_url,
|
||||
is_default: isFirstAccount,
|
||||
created_at: new Date().toISOString(),
|
||||
}
|
||||
|
||||
await saveAccountToken(account.id, trimmedToken)
|
||||
onAccountAdded(account)
|
||||
handleOpenChange(false)
|
||||
} catch (err) {
|
||||
|
||||
@@ -33,6 +33,8 @@ import {
|
||||
getGitHubAccounts,
|
||||
updateGitHubAccounts,
|
||||
validateGitHubToken,
|
||||
getAccountToken,
|
||||
deleteAccountToken,
|
||||
} from "@/lib/tauri"
|
||||
import type {
|
||||
GitDetectResult,
|
||||
@@ -260,10 +262,15 @@ export function VersionControlSettings() {
|
||||
async (account: GitHubAccount) => {
|
||||
setTestingAccountId(account.id)
|
||||
try {
|
||||
const token = await getAccountToken(account.id)
|
||||
if (!token) {
|
||||
toast.error(t("connectionFailed", { message: "Token not found" }))
|
||||
return
|
||||
}
|
||||
if (isGitHubAccount(account)) {
|
||||
const result = await validateGitHubToken(
|
||||
account.server_url,
|
||||
account.token
|
||||
token
|
||||
)
|
||||
if (result.success) {
|
||||
toast.success(t("connectionSuccess"))
|
||||
@@ -276,7 +283,7 @@ export function VersionControlSettings() {
|
||||
}
|
||||
} else {
|
||||
// For non-GitHub accounts we can't validate via API,
|
||||
// just confirm the account is stored.
|
||||
// just confirm the token exists in keyring.
|
||||
toast.success(t("connectionSuccess"))
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -315,6 +322,7 @@ export function VersionControlSettings() {
|
||||
accounts: accounts.accounts.filter((a) => a.id !== removeTarget.id),
|
||||
}
|
||||
try {
|
||||
await deleteAccountToken(removeTarget.id)
|
||||
const saved = await updateGitHubAccounts(updated)
|
||||
setAccounts(saved)
|
||||
toast.success(t("removeSuccess"))
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
validateGitHubToken,
|
||||
getGitHubAccounts,
|
||||
updateGitHubAccounts,
|
||||
saveAccountToken,
|
||||
} from "@/lib/tauri"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -146,14 +147,15 @@ async function saveGenericAccount(
|
||||
(a) => a.username === creds.username && extractHost(a.server_url) === host
|
||||
)
|
||||
if (!isDuplicate) {
|
||||
const newId = crypto.randomUUID()
|
||||
await saveAccountToken(newId, creds.password)
|
||||
await updateGitHubAccounts({
|
||||
accounts: [
|
||||
...existing.accounts,
|
||||
{
|
||||
id: crypto.randomUUID(),
|
||||
id: newId,
|
||||
server_url: serverUrl,
|
||||
username: creds.username,
|
||||
token: creds.password,
|
||||
scopes: [],
|
||||
avatar_url: null,
|
||||
is_default: existing.accounts.length === 0,
|
||||
@@ -284,12 +286,12 @@ export function GitCredentialProvider({ children }: { children: ReactNode }) {
|
||||
id: crypto.randomUUID(),
|
||||
server_url: serverUrl,
|
||||
username: result.username ?? "unknown",
|
||||
token: trimmedToken,
|
||||
scopes: result.scopes,
|
||||
avatar_url: result.avatar_url,
|
||||
is_default: existing.accounts.length === 0,
|
||||
created_at: new Date().toISOString(),
|
||||
}
|
||||
await saveAccountToken(newAccount.id, trimmedToken)
|
||||
await updateGitHubAccounts({
|
||||
accounts: [...existing.accounts, newAccount],
|
||||
})
|
||||
|
||||
@@ -344,6 +344,25 @@ export async function updateGitHubAccounts(
|
||||
return invoke("update_github_accounts", { settings })
|
||||
}
|
||||
|
||||
export async function saveAccountToken(
|
||||
accountId: string,
|
||||
token: string
|
||||
): Promise<void> {
|
||||
return invoke("save_account_token", { accountId, token })
|
||||
}
|
||||
|
||||
export async function getAccountToken(
|
||||
accountId: string
|
||||
): Promise<string | null> {
|
||||
return invoke("get_account_token", { accountId })
|
||||
}
|
||||
|
||||
export async function deleteAccountToken(
|
||||
accountId: string
|
||||
): Promise<void> {
|
||||
return invoke("delete_account_token", { accountId })
|
||||
}
|
||||
|
||||
export async function mcpScanLocal(): Promise<LocalMcpServer[]> {
|
||||
return invoke("mcp_scan_local")
|
||||
}
|
||||
|
||||
@@ -544,7 +544,6 @@ export interface GitHubAccount {
|
||||
id: string
|
||||
server_url: string
|
||||
username: string
|
||||
token: string
|
||||
scopes: string[]
|
||||
avatar_url: string | null
|
||||
is_default: boolean
|
||||
|
||||
Reference in New Issue
Block a user