moving
This commit is contained in:
@@ -2,6 +2,7 @@ import { describe, it, expect, beforeAll, afterAll, vi, beforeEach } from 'vites
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { WaggleConfig } from '@waggle/core';
|
||||
import { buildLocalServer } from '../src/local/index.js';
|
||||
import { injectWithAuth } from './test-utils.js';
|
||||
|
||||
@@ -55,17 +56,187 @@ describe('Team local routes', () => {
|
||||
});
|
||||
|
||||
it('returns 502 when team server is unreachable', async () => {
|
||||
const response = await injectWithAuth(server, {
|
||||
method: 'POST',
|
||||
url: '/api/team/connect',
|
||||
payload: {
|
||||
serverUrl: 'http://localhost:19999',
|
||||
token: 'test-token',
|
||||
},
|
||||
});
|
||||
const previousAllowLocal = process.env.WAGGLE_ALLOW_LOCAL_FETCH;
|
||||
process.env.WAGGLE_ALLOW_LOCAL_FETCH = '1';
|
||||
try {
|
||||
const response = await injectWithAuth(server, {
|
||||
method: 'POST',
|
||||
url: '/api/team/connect',
|
||||
payload: {
|
||||
serverUrl: 'http://localhost:19999',
|
||||
token: 'test-token',
|
||||
},
|
||||
});
|
||||
|
||||
// Should get 502 (bad gateway) or 504 (timeout)
|
||||
expect([502, 504]).toContain(response.statusCode);
|
||||
// Should get 502 (bad gateway) or 504 (timeout)
|
||||
expect([502, 504]).toContain(response.statusCode);
|
||||
} finally {
|
||||
if (previousAllowLocal === undefined) delete process.env.WAGGLE_ALLOW_LOCAL_FETCH;
|
||||
else process.env.WAGGLE_ALLOW_LOCAL_FETCH = previousAllowLocal;
|
||||
}
|
||||
});
|
||||
|
||||
it('blocks cloud metadata targets before fetch or persistence', async () => {
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response('{}', { status: 200 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
try {
|
||||
const response = await injectWithAuth(server, {
|
||||
method: 'POST',
|
||||
url: '/api/team/connect',
|
||||
payload: {
|
||||
serverUrl: 'https://169.254.169.254/latest/meta-data',
|
||||
token: 'metadata-token',
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(502);
|
||||
expect(fetchMock).not.toHaveBeenCalled();
|
||||
const status = await injectWithAuth(server, { method: 'GET', url: '/api/team/status' });
|
||||
expect(JSON.parse(status.body).connected).toBe(false);
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
await injectWithAuth(server, { method: 'POST', url: '/api/team/disconnect' });
|
||||
}
|
||||
});
|
||||
|
||||
it('rejects cleartext public Team URLs before sending the token', async () => {
|
||||
const previousAllowLocal = process.env.WAGGLE_ALLOW_LOCAL_FETCH;
|
||||
process.env.WAGGLE_ALLOW_LOCAL_FETCH = '1';
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response('{}', { status: 200 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
try {
|
||||
const response = await injectWithAuth(server, {
|
||||
method: 'POST',
|
||||
url: '/api/team/connect',
|
||||
payload: { serverUrl: 'http://93.184.216.34', token: 'public-http-token' },
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(400);
|
||||
expect(fetchMock).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
if (previousAllowLocal === undefined) delete process.env.WAGGLE_ALLOW_LOCAL_FETCH;
|
||||
else process.env.WAGGLE_ALLOW_LOCAL_FETCH = previousAllowLocal;
|
||||
await injectWithAuth(server, { method: 'POST', url: '/api/team/disconnect' });
|
||||
}
|
||||
});
|
||||
|
||||
it('accepts a public HTTPS Team URL and stores its canonical base', async () => {
|
||||
const fetchMock = vi.fn()
|
||||
.mockResolvedValueOnce(new Response(null, { status: 200 }))
|
||||
.mockResolvedValueOnce(new Response('[]', { status: 200 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
try {
|
||||
const response = await injectWithAuth(server, {
|
||||
method: 'POST',
|
||||
url: '/api/team/connect',
|
||||
payload: { serverUrl: 'https://93.184.216.34/team/', token: 'public-https-token' },
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(JSON.parse(response.body).serverUrl).toBe('https://93.184.216.34/team');
|
||||
expect(fetchMock.mock.calls.map(([url]) => String(url))).toEqual([
|
||||
'https://93.184.216.34/team/health',
|
||||
'https://93.184.216.34/team/api/teams',
|
||||
]);
|
||||
expect(fetchMock.mock.calls.every(([, init]) => init?.redirect === 'manual')).toBe(true);
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
await injectWithAuth(server, { method: 'POST', url: '/api/team/disconnect' });
|
||||
}
|
||||
});
|
||||
|
||||
it('rejects Team URLs containing credentials before fetch or persistence', async () => {
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response('{}', { status: 200 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
try {
|
||||
const response = await injectWithAuth(server, {
|
||||
method: 'POST',
|
||||
url: '/api/team/connect',
|
||||
payload: { serverUrl: 'https://user:pass@93.184.216.34', token: 'userinfo-token' },
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(400);
|
||||
expect(fetchMock).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
await injectWithAuth(server, { method: 'POST', url: '/api/team/disconnect' });
|
||||
}
|
||||
});
|
||||
|
||||
it('does not forward a Team token across redirects', async () => {
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response(null, {
|
||||
status: 302,
|
||||
headers: { location: 'https://169.254.169.254/latest/meta-data' },
|
||||
}));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
try {
|
||||
const response = await injectWithAuth(server, {
|
||||
method: 'POST',
|
||||
url: '/api/team/connect',
|
||||
payload: { serverUrl: 'https://93.184.216.34', token: 'redirect-token' },
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(502);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(1);
|
||||
expect(fetchMock.mock.calls[0][1]?.redirect).toBe('manual');
|
||||
const status = await injectWithAuth(server, { method: 'GET', url: '/api/team/status' });
|
||||
expect(JSON.parse(status.body).connected).toBe(false);
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
await injectWithAuth(server, { method: 'POST', url: '/api/team/disconnect' });
|
||||
}
|
||||
});
|
||||
|
||||
it('rejects a legacy persisted cleartext public Team URL before sending its token', async () => {
|
||||
const config = new WaggleConfig(tmpDir);
|
||||
config.setTeamServer({
|
||||
url: 'http://93.184.216.34',
|
||||
token: 'legacy-cleartext-token',
|
||||
userId: 'legacy-user',
|
||||
displayName: 'Legacy User',
|
||||
});
|
||||
config.save();
|
||||
const fetchMock = vi.fn().mockResolvedValue(new Response('[]', { status: 200 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
try {
|
||||
const response = await injectWithAuth(server, {
|
||||
method: 'GET',
|
||||
url: '/api/team/teams',
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(502);
|
||||
expect(fetchMock).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
await injectWithAuth(server, { method: 'POST', url: '/api/team/disconnect' });
|
||||
}
|
||||
});
|
||||
|
||||
it('allows an explicitly enabled loopback Team server without following redirects', async () => {
|
||||
const previousAllowLocal = process.env.WAGGLE_ALLOW_LOCAL_FETCH;
|
||||
process.env.WAGGLE_ALLOW_LOCAL_FETCH = '1';
|
||||
const fetchMock = vi.fn()
|
||||
.mockResolvedValueOnce(new Response(null, { status: 200 }))
|
||||
.mockResolvedValueOnce(new Response('[]', { status: 200 }));
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
try {
|
||||
const response = await injectWithAuth(server, {
|
||||
method: 'POST',
|
||||
url: '/api/team/connect',
|
||||
payload: { serverUrl: 'http://127.0.0.1:19999/', token: 'local-token' },
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(JSON.parse(response.body).serverUrl).toBe('http://127.0.0.1:19999');
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2);
|
||||
expect(fetchMock.mock.calls.every(([, init]) => init?.redirect === 'manual')).toBe(true);
|
||||
} finally {
|
||||
vi.unstubAllGlobals();
|
||||
if (previousAllowLocal === undefined) delete process.env.WAGGLE_ALLOW_LOCAL_FETCH;
|
||||
else process.env.WAGGLE_ALLOW_LOCAL_FETCH = previousAllowLocal;
|
||||
await injectWithAuth(server, { method: 'POST', url: '/api/team/disconnect' });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user