mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
82 lines
3.6 KiB
TypeScript
82 lines
3.6 KiB
TypeScript
import { LoginHandler } from '../../../../../../src/identity/interaction/email-password/handler/LoginHandler';
|
|
import type { AccountStore } from '../../../../../../src/identity/interaction/email-password/storage/AccountStore';
|
|
import type {
|
|
Interaction,
|
|
InteractionHandlerInput,
|
|
} from '../../../../../../src/identity/interaction/InteractionHandler';
|
|
import { FoundHttpError } from '../../../../../../src/util/errors/FoundHttpError';
|
|
import { createPostJsonOperation } from './Util';
|
|
|
|
describe('A LoginHandler', (): void => {
|
|
const webId = 'http://alice.test.com/card#me';
|
|
const email = 'alice@test.email';
|
|
let oidcInteraction: jest.Mocked<Interaction>;
|
|
let input: Required<InteractionHandlerInput>;
|
|
let accountStore: jest.Mocked<AccountStore>;
|
|
let handler: LoginHandler;
|
|
|
|
beforeEach(async(): Promise<void> => {
|
|
oidcInteraction = {
|
|
exp: 123456,
|
|
save: jest.fn(),
|
|
} as any;
|
|
|
|
input = { oidcInteraction } as any;
|
|
|
|
accountStore = {
|
|
authenticate: jest.fn().mockResolvedValue(webId),
|
|
getSettings: jest.fn().mockResolvedValue({ useIdp: true }),
|
|
} as any;
|
|
|
|
handler = new LoginHandler(accountStore);
|
|
});
|
|
it('errors if no oidcInteraction is defined on POST requests.', async(): Promise<void> => {
|
|
const error = expect.objectContaining({
|
|
statusCode: 400,
|
|
message: 'This action can only be performed as part of an OIDC authentication flow.',
|
|
errorCode: 'E0002',
|
|
});
|
|
await expect(handler.canHandle({ operation: createPostJsonOperation({}) })).rejects.toThrow(error);
|
|
|
|
await expect(handler.canHandle({ operation: createPostJsonOperation({}), oidcInteraction }))
|
|
.resolves.toBeUndefined();
|
|
});
|
|
|
|
it('errors on invalid emails.', async(): Promise<void> => {
|
|
input.operation = createPostJsonOperation({});
|
|
await expect(handler.handle(input)).rejects.toThrow('Email required');
|
|
input.operation = createPostJsonOperation({ email: [ 'a', 'b' ]});
|
|
await expect(handler.handle(input)).rejects.toThrow('Email required');
|
|
});
|
|
|
|
it('errors on invalid passwords.', async(): Promise<void> => {
|
|
input.operation = createPostJsonOperation({ email });
|
|
await expect(handler.handle(input)).rejects.toThrow('Password required');
|
|
input.operation = createPostJsonOperation({ email, password: [ 'a', 'b' ]});
|
|
await expect(handler.handle(input)).rejects.toThrow('Password required');
|
|
});
|
|
|
|
it('throws an error if there is a problem.', async(): Promise<void> => {
|
|
input.operation = createPostJsonOperation({ email, password: 'password!' });
|
|
accountStore.authenticate.mockRejectedValueOnce(new Error('auth failed!'));
|
|
await expect(handler.handle(input)).rejects.toThrow('auth failed!');
|
|
});
|
|
|
|
it('throws an error if the account does not have the correct settings.', async(): Promise<void> => {
|
|
input.operation = createPostJsonOperation({ email, password: 'password!' });
|
|
accountStore.getSettings.mockResolvedValueOnce({ useIdp: false, clientCredentials: []});
|
|
await expect(handler.handle(input))
|
|
.rejects.toThrow('This server is not an identity provider for this account.');
|
|
});
|
|
|
|
it('returns the generated redirect URL.', async(): Promise<void> => {
|
|
input.operation = createPostJsonOperation({ email, password: 'password!' });
|
|
await expect(handler.handle(input)).rejects.toThrow(FoundHttpError);
|
|
|
|
expect(accountStore.authenticate).toHaveBeenCalledTimes(1);
|
|
expect(accountStore.authenticate).toHaveBeenLastCalledWith(email, 'password!');
|
|
expect(oidcInteraction.save).toHaveBeenCalledTimes(1);
|
|
expect(oidcInteraction.result).toEqual({ login: { accountId: webId, remember: false }});
|
|
});
|
|
});
|