fix: address latest coderabbit review findings

This commit is contained in:
Cita
2026-03-23 15:24:00 +08:00
parent 426d9a538d
commit 764b9aa0e6
21 changed files with 472 additions and 46 deletions
+52 -2
View File
@@ -4,10 +4,11 @@ import {
buildOauthInfoFromAccount,
buildStoredOauthStateFromAccount,
getOauthInfoFromAccount,
isOauthProvider,
} from './oauthAccount.js';
describe('oauth account identity helpers', () => {
it('prefers structured oauth identity columns over extraConfig metadata', () => {
it('prefers structured oauth provider/accountKey/projectId columns while preserving a legacy accountId', () => {
const oauth = getOauthInfoFromAccount({
oauthProvider: 'gemini-cli',
oauthAccountKey: 'structured-user@example.com',
@@ -25,7 +26,7 @@ describe('oauth account identity helpers', () => {
expect(oauth).toEqual(expect.objectContaining({
provider: 'gemini-cli',
accountId: 'structured-user@example.com',
accountId: 'json-user',
accountKey: 'structured-user@example.com',
projectId: 'structured-project',
refreshToken: 'refresh-token',
@@ -82,6 +83,29 @@ describe('oauth account identity helpers', () => {
}));
});
it('preserves legacy accountId when structured oauthAccountKey differs', () => {
const oauth = getOauthInfoFromAccount({
oauthProvider: 'codex',
oauthAccountKey: 'structured-account-key',
oauthProjectId: null,
extraConfig: JSON.stringify({
oauth: {
provider: 'codex',
accountId: 'legacy-account-id',
accountKey: 'legacy-account-key',
refreshToken: 'refresh-token',
},
}),
});
expect(oauth).toEqual(expect.objectContaining({
provider: 'codex',
accountId: 'legacy-account-id',
accountKey: 'structured-account-key',
refreshToken: 'refresh-token',
}));
});
it('builds patched oauth state from structured identity columns and current runtime state', () => {
const oauth = buildOauthInfoFromAccount({
oauthProvider: 'codex',
@@ -135,6 +159,32 @@ describe('oauth account identity helpers', () => {
});
});
it('still recognizes oauth providers from account rows after persisted state strips identity fields', () => {
const account = {
oauthProvider: 'codex',
oauthAccountKey: 'structured-account',
oauthProjectId: 'structured-project',
extraConfig: JSON.stringify({
oauth: buildStoredOauthStateFromAccount({
oauthProvider: 'codex',
oauthAccountKey: 'structured-account',
oauthProjectId: 'structured-project',
extraConfig: JSON.stringify({
oauth: {
provider: 'codex',
accountId: 'legacy-account',
refreshToken: 'refresh-token',
},
}),
}),
}),
};
expect(isOauthProvider(account)).toBe(true);
expect(isOauthProvider(account, 'codex')).toBe(true);
expect(isOauthProvider(account, 'gemini-cli')).toBe(false);
});
it('builds a structured identity backfill patch from legacy oauth metadata only for missing columns', () => {
expect(buildOauthIdentityBackfillPatch({
oauthProvider: null,
+6 -6
View File
@@ -179,11 +179,12 @@ export function getOauthInfoFromAccount(account?: OauthIdentityCarrier | null):
if (!provider) return null;
const structuredAccountKey = asTrimmedString(account.oauthAccountKey);
const accountKey = structuredAccountKey || storedIdentity?.accountKey || storedIdentity?.accountId;
const accountId = storedIdentity?.accountId || structuredAccountKey || accountKey;
const projectId = asTrimmedString(account.oauthProjectId) || storedIdentity?.projectId;
return {
...(storedRuntime || {}),
provider,
accountId: structuredAccountKey || storedIdentity?.accountId || accountKey,
accountId,
accountKey,
projectId,
};
@@ -275,13 +276,12 @@ export function buildStoredOauthStateFromAccount(
}
export function isOauthProvider(
account: Pick<typeof schema.accounts.$inferSelect, 'extraConfig'> | string | null | undefined,
account: OauthIdentityCarrier | string | null | undefined,
provider?: string,
): boolean {
const extraConfig = typeof account === 'string' || account == null
? account
: account.extraConfig;
const oauth = getOauthInfoFromExtraConfig(extraConfig);
const oauth = typeof account === 'string' || account == null
? getOauthInfoFromExtraConfig(account)
: getOauthInfoFromAccount(account);
if (!oauth) return false;
if (!provider) return true;
return oauth.provider === provider;