mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-18 00:14:48 +00:00
fix(cliproxy): use nickname as accountId for kiro/ghcp providers
Kiro/GHCP OAuth tokens have empty email field, causing all accounts to use accountId='default' and overwrite each other. This fix: - Add PROVIDERS_WITHOUT_EMAIL constant for kiro/ghcp identification - Require nickname for kiro/ghcp during registration (CLI + web UI) - Use nickname as accountId instead of email for these providers - Enforce nickname uniqueness to prevent collisions - Update discoverExistingAccounts() to generate unique IDs (kiro-1, etc.) Closes #258, #267
This commit is contained in:
1 parent
497fc2a9c0
commit
d96c67ba81
4 files changed
+271
-14
No files matched your search
@@ -164,7 +164,7 @@ describe('Account Manager - discoverExistingAccounts', () => {
|
||||
assert.strictEqual(accountIds[0], 'actual@email.com', 'Should use data.email when available');
|
||||
});
|
||||
|
||||
it('falls back to "default" when no email in file or filename', () => {
|
||||
it('generates unique ID for kiro/ghcp when no email in file or filename', () => {
|
||||
createAuthFile('kiro-nomail.json', {
|
||||
type: 'kiro',
|
||||
email: '',
|
||||
@@ -174,7 +174,8 @@ describe('Account Manager - discoverExistingAccounts', () => {
|
||||
const accounts = getAccountsFile();
|
||||
|
||||
const accountIds = Object.keys(accounts.providers.kiro.accounts);
|
||||
assert.strictEqual(accountIds[0], 'default', 'Should fall back to "default"');
|
||||
// For kiro/ghcp without email, generates unique ID like "kiro-1"
|
||||
assert.strictEqual(accountIds[0], 'kiro-1', 'Should generate unique ID for kiro without email');
|
||||
});
|
||||
|
||||
it('handles dots in email local part', () => {
|
||||
@@ -274,6 +275,72 @@ describe('Account Manager - discoverExistingAccounts', () => {
|
||||
'First account should be default'
|
||||
);
|
||||
});
|
||||
|
||||
it('generates sequential IDs for multiple kiro files without email', () => {
|
||||
// Create multiple kiro files without email in filename
|
||||
// Files like "kiro-nomail.json" don't match oauth pattern (need 2+ hyphens)
|
||||
createAuthFile('kiro-account1.json', {
|
||||
type: 'kiro',
|
||||
email: '',
|
||||
});
|
||||
createAuthFile('kiro-account2.json', {
|
||||
type: 'kiro',
|
||||
email: '',
|
||||
});
|
||||
|
||||
accountManager.discoverExistingAccounts();
|
||||
const accounts = getAccountsFile();
|
||||
|
||||
const accountIds = Object.keys(accounts.providers.kiro.accounts);
|
||||
assert.strictEqual(accountIds.length, 2, 'Should have 2 accounts');
|
||||
// Both should have kiro-N format since filenames don't match oauth pattern (1 hyphen only)
|
||||
assert(accountIds.includes('kiro-1'), 'Should have kiro-1');
|
||||
assert(accountIds.includes('kiro-2'), 'Should have kiro-2');
|
||||
});
|
||||
|
||||
it('skips to next ID when collision exists', () => {
|
||||
// Pre-create accounts.json with kiro-1 already registered
|
||||
const accountsPath = path.join(testDir, '.ccs', 'cliproxy', 'accounts.json');
|
||||
const existingRegistry = {
|
||||
version: 1,
|
||||
providers: {
|
||||
kiro: {
|
||||
default: 'kiro-1',
|
||||
accounts: {
|
||||
'kiro-1': {
|
||||
tokenFile: 'kiro-existing.json',
|
||||
createdAt: new Date().toISOString(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
fs.writeFileSync(accountsPath, JSON.stringify(existingRegistry));
|
||||
|
||||
// Create the existing token file (matches registry)
|
||||
createAuthFile('kiro-existing.json', {
|
||||
type: 'kiro',
|
||||
email: '',
|
||||
});
|
||||
|
||||
// Create new file that will need auto-generated ID (single hyphen = no oauth pattern match)
|
||||
createAuthFile('kiro-newaccount.json', {
|
||||
type: 'kiro',
|
||||
email: '',
|
||||
});
|
||||
|
||||
// Reload module to pick up pre-existing accounts.json
|
||||
delete require.cache[require.resolve('../../../dist/cliproxy/account-manager')];
|
||||
accountManager = require('../../../dist/cliproxy/account-manager');
|
||||
accountManager.discoverExistingAccounts();
|
||||
|
||||
const accounts = getAccountsFile();
|
||||
const accountIds = Object.keys(accounts.providers.kiro.accounts);
|
||||
|
||||
assert.strictEqual(accountIds.length, 2, 'Should have 2 accounts');
|
||||
assert(accountIds.includes('kiro-1'), 'Should keep existing kiro-1');
|
||||
assert(accountIds.includes('kiro-2'), 'New account should be kiro-2 (skipped kiro-1)');
|
||||
});
|
||||
});
|
||||
|
||||
// =========================================================================
|
||||
|
||||
Reference in new issue
Block a user