discourse/test/javascripts/acceptance/password-reset-test.js.es6
Jeff Wong f4f8a293e7 FEATURE: Implement 2factor login TOTP
implemented review items.

Blocking previous codes - valid 2-factor auth tokens can only be authenticated once/30 seconds.
I played with updating the “last used” any time the token was attempted but that seemed to be overkill, and frustrating as to why a token would fail.
Translatable texts.
Move second factor logic to a helper class.
Move second factor specific controller endpoints to its own controller.
Move serialization logic for 2-factor details in admin user views.
Add a login ember component for de-duplication
Fix up code formatting
Change verbiage of google authenticator

add controller tests:
second factor controller tests
change email tests
change password tests
admin login tests

add qunit tests - password reset, preferences

fix: check for 2factor on change email controller
fix: email controller - only show second factor errors on attempt
fix: check against 'true' to enable second factor.

Add modal for explaining what 2fa with links to Google Authenticator/FreeOTP

add two factor to email signin link

rate limit if second factor token present

add rate limiter test for second factor attempts
2018-02-21 09:04:07 +08:00

107 lines
3.8 KiB
JavaScript

import { acceptance } from "helpers/qunit-helpers";
import PreloadStore from 'preload-store';
import { parsePostData } from "helpers/create-pretender";
acceptance("Password Reset", {
beforeEach() {
const response = (object) => {
return [
200,
{"Content-Type": "application/json"},
object
];
};
server.get('/u/confirm-email-token/myvalidtoken.json', () => { //eslint-disable-line
return response({success: "OK"});
});
server.put('/u/password-reset/myvalidtoken.json', request => { //eslint-disable-line
const body = parsePostData(request.requestBody);
if (body.password === "jonesyAlienSlayer") {
return response({success: false, errors: {password: ["is the name of your cat"]}});
} else {
return response({success: "OK", message: I18n.t('password_reset.success')});
}
});
server.get('/u/confirm-email-token/requiretwofactor.json', () => { //eslint-disable-line
return response({success: "OK"});
});
server.put('/u/password-reset/requiretwofactor.json', request => { //eslint-disable-line
const body = parsePostData(request.requestBody);
if (body.password === "perf3ctly5ecur3" && body.second_factor_token === "123123") {
return response({success: "OK", message: I18n.t('password_reset.success')});
} else if (body.second_factor_token === "123123") {
return response({success: false, errors: {password: ["invalid"]}});
} else {
return response({success: false, message: "invalid token", errors: {second_factor: ["invalid token"]}});
}
});
}
});
QUnit.test("Password Reset Page", assert => {
PreloadStore.store('password_reset', {is_developer: false});
visit("/u/password-reset/myvalidtoken");
andThen(() => {
assert.ok(exists(".password-reset input"), "shows the input");
});
fillIn('.password-reset input', 'perf3ctly5ecur3');
andThen(() => {
assert.ok(exists(".password-reset .tip.good"), "input looks good");
});
fillIn('.password-reset input', '123');
andThen(() => {
assert.ok(exists(".password-reset .tip.bad"), "input is not valid");
assert.ok(find(".password-reset .tip.bad").html().indexOf(I18n.t('user.password.too_short')) > -1, "password too short");
});
fillIn('.password-reset input', 'jonesyAlienSlayer');
click('.password-reset form button');
andThen(() => {
assert.ok(exists(".password-reset .tip.bad"), "input is not valid");
assert.ok(find(".password-reset .tip.bad").html().indexOf("is the name of your cat") > -1, "server validation error message shows");
});
fillIn('.password-reset input', 'perf3ctly5ecur3');
click('.password-reset form button');
andThen(() => {
assert.ok(!exists(".password-reset form"), "form is gone");
});
});
QUnit.test("Password Reset Page With Second Factor", assert => {
PreloadStore.store('password_reset', {is_developer: false, second_factor_required: true});
visit("/u/password-reset/requiretwofactor");
andThen(() => {
assert.notOk(exists("#new-account-password"), "does not show the input");
assert.ok(exists("#second-factor"), "shows the second factor prompt");
});
fillIn('#second-factor', '0000');
click('.password-reset form button');
andThen(() => {
assert.ok(exists(".alert-error"), "shows 2 factor error");
assert.ok(find(".alert-error").html().indexOf("invalid token") > -1, "server validation error message shows");
});
fillIn('#second-factor', '123123');
click('.password-reset form button');
andThen(() => {
assert.notOk(exists(".alert-error"), "hides error");
assert.ok(exists("#new-account-password"), "shows the input");
});
fillIn('.password-reset input', 'perf3ctly5ecur3');
click('.password-reset form button');
andThen(() => {
assert.ok(!exists(".password-reset form"), "form is gone");
});
});