fix(auth): unify imported sessions with account gating
This commit is contained in:
1 parent
654bbda457
commit
ea92a1a92b
15 files changed
+123
-49
No files matched your search
@@ -270,7 +270,7 @@ describe('settings and access', () => {
|
||||
renderSettings('/settings?section=access');
|
||||
|
||||
expect(await screen.findByText('Login required')).toBeInTheDocument();
|
||||
expect(screen.getByText(/waiting for a session dump/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/waiting for a fresh session dump/i)).toBeInTheDocument();
|
||||
expect(screen.queryByText(/noVNC/i)).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole('textbox', { name: /password/i })).not.toBeInTheDocument();
|
||||
|
||||
|
||||
@@ -27,6 +27,10 @@ function appWithBrowser(state: 'authenticated' | 'login-required' | 'unreachable
|
||||
app.use(
|
||||
createLoginRouter({
|
||||
services: {
|
||||
accountAuth: {
|
||||
ensureFullyAuthenticated: async () => state === 'authenticated',
|
||||
getSnapshot: () => ({ redditUsername: state === 'authenticated' ? 'example-account' : null }),
|
||||
},
|
||||
browser: {
|
||||
isSessionValid: async () => state === 'authenticated',
|
||||
getAuthenticatedUsername: async () => state === 'authenticated' ? 'example-account' : null,
|
||||
|
||||
@@ -15,11 +15,16 @@ const credentials = {
|
||||
|
||||
describe('RedditSessionImporter', () => {
|
||||
it('verifies both parts of the dump before activating the account', async () => {
|
||||
const browser = { importRedditCookies: vi.fn(), isSessionValid: vi.fn(async () => true) };
|
||||
const browser = {
|
||||
importRedditCookies: vi.fn(),
|
||||
isSessionValid: vi.fn(async () => true),
|
||||
getAuthenticatedUsername: vi.fn(async () => 'bot-account'),
|
||||
};
|
||||
const matrix = { whoami: vi.fn(async () => credentials.userId) };
|
||||
const chat = { setMatrixClient: vi.fn() };
|
||||
const save = vi.fn();
|
||||
const importer = new RedditSessionImporter(browser, chat as never, vi.fn(() => matrix as never), save);
|
||||
const accountAuth = { markAuthenticated: vi.fn() };
|
||||
const importer = new RedditSessionImporter(browser, chat as never, vi.fn(() => matrix as never), save, accountAuth as never);
|
||||
|
||||
await importer.import(cookies, credentials);
|
||||
|
||||
@@ -27,15 +32,21 @@ describe('RedditSessionImporter', () => {
|
||||
expect(browser.importRedditCookies).toHaveBeenCalledWith(cookies);
|
||||
expect(chat.setMatrixClient).toHaveBeenCalledWith(matrix);
|
||||
expect(save).toHaveBeenCalledWith(credentials);
|
||||
expect(accountAuth.markAuthenticated).toHaveBeenCalledWith({
|
||||
accountId: credentials.userId,
|
||||
redditUsername: 'bot-account',
|
||||
matrixUserId: credentials.userId,
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects non-Reddit Matrix homeservers without making a request', async () => {
|
||||
const createMatrix = vi.fn();
|
||||
const importer = new RedditSessionImporter(
|
||||
{ importRedditCookies: vi.fn(), isSessionValid: vi.fn() },
|
||||
{ importRedditCookies: vi.fn(), isSessionValid: vi.fn(), getAuthenticatedUsername: vi.fn() },
|
||||
{ setMatrixClient: vi.fn() } as never,
|
||||
createMatrix,
|
||||
vi.fn(),
|
||||
{ markAuthenticated: vi.fn() } as never,
|
||||
);
|
||||
|
||||
await expect(importer.import(cookies, { ...credentials, homeserver: 'https://attacker.example' }))
|
||||
|
||||
@@ -7,22 +7,19 @@ describe('SessionBoundRuntime', () => {
|
||||
const stop = vi.fn();
|
||||
const runtime = new SessionBoundRuntime(start, stop);
|
||||
|
||||
expect(runtime.reconcile('login-required')).toBe(false);
|
||||
expect(runtime.reconcile(false)).toBe(false);
|
||||
expect(start).not.toHaveBeenCalled();
|
||||
|
||||
expect(runtime.reconcile('authenticated')).toBe(true);
|
||||
expect(runtime.reconcile('authenticated')).toBe(true);
|
||||
expect(runtime.reconcile(true)).toBe(true);
|
||||
expect(runtime.reconcile(true)).toBe(true);
|
||||
expect(start).toHaveBeenCalledOnce();
|
||||
|
||||
expect(runtime.reconcile('login-required')).toBe(false);
|
||||
expect(runtime.reconcile(false)).toBe(false);
|
||||
expect(stop).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it.each(['unknown', 'login-required', 'unreachable'] as const)(
|
||||
'treats %s as waiting for an extension dump',
|
||||
(state) => {
|
||||
const runtime = new SessionBoundRuntime(vi.fn(), vi.fn());
|
||||
expect(runtime.reconcile(state)).toBe(false);
|
||||
},
|
||||
);
|
||||
it('treats incomplete authentication as waiting for an extension dump', () => {
|
||||
const runtime = new SessionBoundRuntime(vi.fn(), vi.fn());
|
||||
expect(runtime.reconcile(false)).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -10,6 +10,7 @@ describe('control route realtime events', () => {
|
||||
const bot = vi.fn();
|
||||
const context = {
|
||||
config: { browser: { dryRun: true } },
|
||||
services: { accountAuth: { isFullyAuthenticated: () => true } },
|
||||
setBotRunning: (next: boolean) => { running = next; },
|
||||
activity: { push: vi.fn() },
|
||||
logger: { info: vi.fn() },
|
||||
|
||||
Reference in new issue
Block a user