Download packages/kap-server/test/authTokenStore.test.ts from SaylorTwift/kimi-code: direct link, hf CLI and curl.
- Browser
- Download file 8.55 kB
-
https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/kap-server/test/authTokenStore.test.ts
- Command line
-
hf download hf://SaylorTwift/kimi-code/packages/kap-server/test/authTokenStore.test.ts
-
curl -L -o authTokenStore.test.ts https://huggingface.co/SaylorTwift/kimi-code/resolve/main/packages/kap-server/test/authTokenStore.test.ts
8.55 kB
| import { | |
| chmodSync, | |
| existsSync, | |
| mkdtempSync, | |
| readFileSync, | |
| rmSync, | |
| statSync, | |
| writeFileSync, | |
| } from 'node:fs'; | |
| import { tmpdir } from 'node:os'; | |
| import { join } from 'node:path'; | |
| import { afterEach, beforeEach, describe, expect, it } from 'vitest'; | |
| import { | |
| PrivateFileTooPermissiveError, | |
| readPrivateFile, | |
| writePrivateFile, | |
| } from '../src/services/auth/privateFiles'; | |
| import { | |
| loadOrCreateServerToken, | |
| rotateServerToken, | |
| } from '../src/services/auth/persistentToken'; | |
| import { createTokenStore } from '../src/services/auth/tokenStore'; | |
| import { createAuthTokenService } from '../src/services/auth/authTokenService'; | |
| import { resolvePasswordHash, verifyPassword } from '../src/services/auth/password'; | |
| let tmpDir: string; | |
| beforeEach(() => { | |
| tmpDir = mkdtempSync(join(tmpdir(), 'kimi-server-v2-auth-token-')); | |
| }); | |
| afterEach(() => { | |
| rmSync(tmpDir, { recursive: true, force: true }); | |
| }); | |
| describe('privateFiles', () => { | |
| it.skipIf(process.platform === 'win32')('writes a file with mode 0600', async () => { | |
| const p = join(tmpDir, 'secret'); | |
| await writePrivateFile(p, 'hello'); | |
| expect(statSync(p).mode & 0o777).toBe(0o600); | |
| }); | |
| it.skipIf(process.platform === 'win32')('creates an absent parent dir with mode 0700', async () => { | |
| const p = join(tmpDir, 'nested', 'dir', 'secret'); | |
| await writePrivateFile(p, 'hello'); | |
| expect(statSync(join(tmpDir, 'nested', 'dir')).mode & 0o777).toBe(0o700); | |
| }); | |
| it('round-trips string content through readPrivateFile', async () => { | |
| const p = join(tmpDir, 'secret'); | |
| await writePrivateFile(p, 's3cr3t-value'); | |
| const buf = await readPrivateFile(p); | |
| expect(buf.toString('utf8')).toBe('s3cr3t-value'); | |
| }); | |
| it('round-trips Buffer content through readPrivateFile', async () => { | |
| const p = join(tmpDir, 'bin'); | |
| const data = Buffer.from([0, 1, 2, 254, 255]); | |
| await writePrivateFile(p, data); | |
| const buf = await readPrivateFile(p); | |
| expect(buf.equals(data)).toBe(true); | |
| }); | |
| it.skipIf(process.platform === 'win32')('readPrivateFile throws on a 0644 file', async () => { | |
| const p = join(tmpDir, 'leaky'); | |
| writeFileSync(p, 'x', { mode: 0o644 }); | |
| chmodSync(p, 0o644); | |
| await expect(readPrivateFile(p)).rejects.toThrowError(PrivateFileTooPermissiveError); | |
| }); | |
| }); | |
| describe('tokenStore', () => { | |
| it('returns the same token from repeated getToken() calls', async () => { | |
| const store = await createTokenStore(join(tmpDir, 'home')); | |
| expect(store.getToken()).toBe(store.getToken()); | |
| await store.dispose(); | |
| }); | |
| it('produces different tokens for different home dirs', async () => { | |
| const a = await createTokenStore(join(tmpDir, 'home-a')); | |
| const b = await createTokenStore(join(tmpDir, 'home-b')); | |
| expect(a.getToken()).not.toBe(b.getToken()); | |
| await a.dispose(); | |
| await b.dispose(); | |
| }); | |
| it('reuses the same persistent token across stores in one home dir', async () => { | |
| const home = join(tmpDir, 'home'); | |
| const a = await createTokenStore(home); | |
| const token = a.getToken(); | |
| await a.dispose(); | |
| const b = await createTokenStore(home); | |
| expect(b.getToken()).toBe(token); | |
| await b.dispose(); | |
| }); | |
| it.skipIf(process.platform === 'win32')('writes the token file with mode 0600 at server.token', async () => { | |
| const home = join(tmpDir, 'home'); | |
| const store = await createTokenStore(home); | |
| expect(store.tokenPath).toBe(join(home, 'server.token')); | |
| expect(statSync(store.tokenPath).mode & 0o777).toBe(0o600); | |
| await store.dispose(); | |
| }); | |
| it('isValid accepts the token and rejects wrong / empty / same-length candidates', async () => { | |
| const store = await createTokenStore(join(tmpDir, 'home')); | |
| const token = store.getToken(); | |
| expect(store.isValid(token)).toBe(true); | |
| expect(store.isValid('wrong')).toBe(false); | |
| expect(store.isValid('')).toBe(false); | |
| const other = await createTokenStore(join(tmpDir, 'home-other')); | |
| expect(other.getToken().length).toBe(token.length); | |
| expect(store.isValid(other.getToken())).toBe(false); | |
| await store.dispose(); | |
| await other.dispose(); | |
| }); | |
| it('dispose() keeps the persistent token file on disk', async () => { | |
| const store = await createTokenStore(join(tmpDir, 'home')); | |
| expect(existsSync(store.tokenPath)).toBe(true); | |
| await store.dispose(); | |
| expect(existsSync(store.tokenPath)).toBe(true); | |
| }); | |
| it('re-reads the token after the file is rewritten (live rotation)', async () => { | |
| const home = join(tmpDir, 'home'); | |
| const store = await createTokenStore(home); | |
| const original = store.getToken(); | |
| const rotated = 'r'.repeat(original.length); | |
| await writePrivateFile(store.tokenPath, rotated); | |
| expect(store.getToken()).toBe(rotated); | |
| expect(store.isValid(rotated)).toBe(true); | |
| expect(store.isValid(original)).toBe(false); | |
| await store.dispose(); | |
| }); | |
| }); | |
| describe('persistentToken', () => { | |
| it('loadOrCreateServerToken generates once and reuses thereafter', async () => { | |
| const home = join(tmpDir, 'home'); | |
| const a = await loadOrCreateServerToken(home); | |
| const b = await loadOrCreateServerToken(home); | |
| expect(a).toBe(b); | |
| }); | |
| it.skipIf(process.platform === 'win32')('writes server.token with mode 0600', async () => { | |
| const home = join(tmpDir, 'home'); | |
| await loadOrCreateServerToken(home); | |
| expect(statSync(join(home, 'server.token')).mode & 0o777).toBe(0o600); | |
| }); | |
| it('rotateServerToken writes a new, different token to server.token', async () => { | |
| const home = join(tmpDir, 'home'); | |
| const original = await loadOrCreateServerToken(home); | |
| const rotated = await rotateServerToken(home); | |
| expect(rotated).not.toBe(original); | |
| expect(readFileSync(join(home, 'server.token'), 'utf8').trim()).toBe(rotated); | |
| }); | |
| }); | |
| describe('password', () => { | |
| it('resolvePasswordHash returns undefined when env is unset or empty', async () => { | |
| expect(await resolvePasswordHash({})).toBeUndefined(); | |
| expect(await resolvePasswordHash({ KIMI_CODE_PASSWORD: '' })).toBeUndefined(); | |
| }); | |
| it('hashes a set password with bcrypt and verifies correctly', async () => { | |
| const passwordHash = await resolvePasswordHash({ | |
| KIMI_CODE_PASSWORD: 'correct-horse-battery-staple', | |
| }); | |
| expect(passwordHash?.startsWith('$2')).toBe(true); | |
| expect(await verifyPassword('correct-horse-battery-staple', passwordHash)).toBe(true); | |
| expect(await verifyPassword('wrong-password', passwordHash)).toBe(false); | |
| }); | |
| it('verifyPassword returns false when the hash is undefined', async () => { | |
| expect(await verifyPassword('anything', undefined)).toBe(false); | |
| }); | |
| }); | |
| describe('createAuthTokenService', () => { | |
| it('getToken() returns the tokenStore token', async () => { | |
| const store = await createTokenStore(join(tmpDir, 'home')); | |
| const svc = createAuthTokenService({ tokenStore: store, passwordHash: undefined }); | |
| expect(svc.getToken()).toBe(store.getToken()); | |
| await store.dispose(); | |
| }); | |
| it('isValid accepts the token', async () => { | |
| const store = await createTokenStore(join(tmpDir, 'home')); | |
| const svc = createAuthTokenService({ tokenStore: store, passwordHash: undefined }); | |
| expect(await svc.isValid(store.getToken())).toBe(true); | |
| await store.dispose(); | |
| }); | |
| it('isValid accepts the password when a hash is configured', async () => { | |
| const store = await createTokenStore(join(tmpDir, 'home')); | |
| const passwordHash = await resolvePasswordHash({ | |
| KIMI_CODE_PASSWORD: 'correct horse battery staple', | |
| }); | |
| const svc = createAuthTokenService({ tokenStore: store, passwordHash }); | |
| expect(await svc.isValid('correct horse battery staple')).toBe(true); | |
| await store.dispose(); | |
| }); | |
| it('isValid rejects a wrong candidate', async () => { | |
| const store = await createTokenStore(join(tmpDir, 'home')); | |
| const passwordHash = await resolvePasswordHash({ | |
| KIMI_CODE_PASSWORD: 'correct horse battery staple', | |
| }); | |
| const svc = createAuthTokenService({ tokenStore: store, passwordHash }); | |
| expect(await svc.isValid('wrong')).toBe(false); | |
| await store.dispose(); | |
| }); | |
| it('isValid accepts only the token when passwordHash is undefined', async () => { | |
| const store = await createTokenStore(join(tmpDir, 'home')); | |
| const svc = createAuthTokenService({ tokenStore: store, passwordHash: undefined }); | |
| expect(await svc.isValid(store.getToken())).toBe(true); | |
| expect(await svc.isValid('any-password')).toBe(false); | |
| await store.dispose(); | |
| }); | |
| }); | |