Skip to content

Commit

Permalink
Have players confirm their new password
Browse files Browse the repository at this point in the history
Fixes #573
  • Loading branch information
RussellLVP committed May 15, 2020
1 parent 6206e4a commit fef63b3
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
14 changes: 9 additions & 5 deletions javascript/components/dialogs/question.js
Expand Up @@ -22,15 +22,17 @@ const PrivateSymbol = Symbol('Please use the static methods.');
class Question {
// Asks |question| to |player|, optionally constrained by the |constraints|. Returns a promise
// that will be resolved with the answer when available or NULL when no answer has been entered.
static ask(player, { question, message = null, leftButton = 'Next', constraints = {} } = {}) {
static ask(player, { question, message = null, leftButton = 'Next', isPrivate = false,
constraints = {} } = {}) {
const checkedConstraints = {
validation: constraints.validation || null,
explanation: constraints.explanation || null,
abort: constraints.abort || null
};

const questionInstance =
new Question(PrivateSymbol, player, question, message, leftButton, checkedConstraints);
new Question(PrivateSymbol, player, question, message, leftButton, isPrivate,
checkedConstraints);

// Immediately ask the question to the user.
questionInstance.askPlayer();
Expand All @@ -45,14 +47,16 @@ class Question {
',' + maximumLength + '}$', 'u');
}

constructor(privateSymbol, player, question, message, leftButton, constraints) {
constructor(privateSymbol, player, question, message, leftButton, isPrivate, constraints) {
if (privateSymbol !== PrivateSymbol)
throw new TypeError('Illegal constructor. Use the static methods instead.');

this.player_ = player;
this.question_ = question;
this.leftButton_ = leftButton;
this.constraints_ = constraints;
this.isPrivate_ = isPrivate;

this.constraints_ = constraints;

this.message_ = message;

Expand All @@ -78,7 +82,7 @@ class Question {
message: this.message_,
leftButton: this.leftButton_,
rightButton: 'Cancel',
isPrivate: false
isPrivate: this.isPrivate_
};

Dialog.displayInput(this.player_, dialogOptions).then(async (result) => {
Expand Down
18 changes: 18 additions & 0 deletions javascript/features/account/account_commands.js
Expand Up @@ -208,6 +208,7 @@ export class AccountCommands {
const verifyCurrentPassword = await Question.ask(player, {
question: 'Changing your password',
message: 'Enter your current password to verify your identity',
isPrivate: true, // display this as a password
constraints: {
validation: AccountDatabase.prototype.validatePassword.bind(
this.database_, player.name),
Expand All @@ -225,6 +226,7 @@ export class AccountCommands {
const password = await Question.ask(player, {
question: 'Changing your password',
message: 'Enter the new password that you have in mind',
isPrivate: true, // display this as a password field
constraints: {
validation: AccountCommands.prototype.isSufficientlySecurePassword.bind(this),
explanation: 'The password must be at least 8 characters long, and contain at ' +
Expand All @@ -236,6 +238,22 @@ export class AccountCommands {
if (!password)
return; // the user aborted out of the flow

// The |player| must confirm that they indeed picked the right password, so we ask again.
const confirmPassword = await Question.ask(player, {
question: 'Changing your password',
message: 'Please enter your password again to verify.',
isPrivate: true, // display this as a password field
constraints: {
validation: input => input === password,
explanation: 'You must enter exactly the same password again to make sure that ' +
'you didn\'t accidentally misspell it.',
abort: 'Sorry, you need to confirm your password!'
}
});

if (!confirmPassword || confirmPassword !== password)
return; // the user aborted out of the flow

// Now execute the command to actually change the password in the database.
await this.database_.changePassword(player.name, password);

Expand Down
19 changes: 17 additions & 2 deletions javascript/features/account/account_commands.test.js
Expand Up @@ -106,7 +106,7 @@ describe('AccountCommands', (it, beforeEach, afterEach) => {
() => gunther.respondToDialog({ response: 0 /* Dismiss */ }));

assert.isTrue(await gunther.issueCommand('/account'));
assert.includes(gunther.lastDialog, 'only been 14 days since you');
assert.includes(gunther.lastDialog, 'only been 13 days since you');

assert.equal(database.passwordQueries.length, 0);
assert.isNull(database.nameMutation);
Expand Down Expand Up @@ -272,15 +272,30 @@ describe('AccountCommands', (it, beforeEach, afterEach) => {
assert.equal(database.passwordQueries.length, 6);
assert.equal(database.changePassQueries.length, 0);

// (4) The player is able to change their password.
// (5) The user needs to confirm the password they want to change theirs to.
gunther.respondToDialog({ listitem: 1 /* Change your password */ }).then(
() => gunther.respondToDialog({ inputtext: 'correct-pass' })).then(
() => gunther.respondToDialog({ inputtext: 'new-pass' })).then(
() => gunther.respondToDialog({ inputtext: 'new-pazz' })).then( // <-- typo!
() => gunther.respondToDialog({ response: 0 /* Dismiss */ }));

assert.isTrue(await gunther.issueCommand('/account'));

assert.equal(database.passwordQueries.length, 7);
assert.equal(database.changePassQueries.length, 0);

assert.includes(gunther.lastDialog, 'enter exactly the same password again');

// (4) The player is able to change their password.
gunther.respondToDialog({ listitem: 1 /* Change your password */ }).then(
() => gunther.respondToDialog({ inputtext: 'correct-pass' })).then(
() => gunther.respondToDialog({ inputtext: 'new-pass' })).then(
() => gunther.respondToDialog({ inputtext: 'new-pass' })).then(
() => gunther.respondToDialog({ response: 0 /* Dismiss */ }));

assert.isTrue(await gunther.issueCommand('/account'));

assert.equal(database.passwordQueries.length, 8);
assert.equal(database.changePassQueries.length, 1);
assert.equal(database.changePassQueries[0].nickname, 'Gunther');

Expand Down
2 changes: 1 addition & 1 deletion javascript/features/account/test/mock_account_database.js
Expand Up @@ -149,7 +149,7 @@ export class MockAccountDatabase extends AccountDatabase {
return [
{
nickname: '[HOT]Lad1992',
date: new Date(Date.now() - 14 * 86400 * 1000),
date: new Date(Date.now() - 13 * 86400 * 1000),
},
{
nickname: 'Beamer',
Expand Down

0 comments on commit fef63b3

Please sign in to comment.