Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/plugins/profile/password-reset.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ class PasswordReset extends CustomElement {
static get properties () {
return {
passwords_mismatched: { type: Boolean },
current_password_error: { type: Boolean },
alert_message: { type: String }
}
}

initialize () {
this.passwords_mismatched = false;
this.current_password_error = false;
this.alert_message = '';
}

Expand All @@ -33,9 +35,22 @@ class PasswordReset extends CustomElement {
return this.passwords_mismatched
}

checkCurrentPassword (ev) {
const form_data = new FormData(ev.target.form ?? ev.target);
const current_password = form_data.get('current_password');
const connection = api.connection.get();
if (connection?.pass && current_password !== connection.pass) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't going to work in all cases. When you reconnected via BOSH or XEP-0198 then the password won't be set on the connection object.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To properly test the existing password, you might have to create a new Strophe.Connection object (using the subclass in Converse is likely overkill) and then test logging in with that connection and the provided password.

this.current_password_error = true;
} else {
this.current_password_error = false;
}
return this.current_password_error;
}

async onSubmit (ev) {
ev.preventDefault();

if (this.checkCurrentPassword(ev)) return;
if (this.checkPasswordsMatch(ev)) return;

const domain = _converse.session.get('domain');
Expand Down
17 changes: 17 additions & 0 deletions src/plugins/profile/templates/password-reset.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,29 @@ import { html } from 'lit';
export default el => {
const i18n_submit = __('Submit');
const i18n_passwords_must_match = __('The new passwords must match');
const i18n_current_password = __('Current password');
const i18n_current_password_wrong = __('Incorrect current password');
const i18n_new_password = __('New password');
const i18n_confirm_password = __('Confirm new password');

return html`<form class="converse-form passwordreset-form" method="POST" @submit=${ev => el.onSubmit(ev)}>
${el.alert_message ? html`<div class="alert alert-danger" role="alert">${el.alert_message}</div>` : ''}

<div class="py-2">
<label for="converse_password_reset_current" class="form-label">${i18n_current_password}</label>
<input
class="form-control ${el.current_password_error ? 'error' : ''}"
type="password"
value=""
name="current_password"
required="required"
id="converse_password_reset_current"
autocomplete="current-password"
?disabled="${el.alert_message}"
/>
${el.current_password_error ? html`<span class="error">${i18n_current_password_wrong}</span>` : ''}
</div>

<div class="py-2">
<label for="converse_password_reset_new" class="form-label">${i18n_new_password}</label>
<input
Expand Down
20 changes: 19 additions & 1 deletion src/plugins/profile/tests/password-reset.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const { Strophe, u } = converse.env;

async function submitPasswordResetForm (_converse) {
async function submitPasswordResetForm (_converse, current_password='secret') {
await mock.openControlBox(_converse);
const cbview = _converse.chatboxviews.get('controlbox');
cbview.querySelector('a.show-profile')?.click();
Expand All @@ -12,6 +12,8 @@ async function submitPasswordResetForm (_converse) {
modal.querySelector('#passwordreset-tab').click();
const form = await u.waitUntil(() => modal.querySelector('.passwordreset-form'));

const current_pw_input = form.querySelector('input[name="current_password"]');
current_pw_input.value = current_password;
const pw_input = form.querySelector('input[name="password"]');
pw_input.value = 'secret-password';
const pw_check_input = form.querySelector('input[name="password_check"]');
Expand All @@ -23,6 +25,22 @@ async function submitPasswordResetForm (_converse) {


describe('The profile modal', function () {
it(
'shows an error if the current password is incorrect',
mock.initConverse([], {}, async function (_converse) {
const modal = await submitPasswordResetForm(_converse, 'wrong-password');

const form = await u.waitUntil(() => modal.querySelector('.passwordreset-form'));
const error = await u.waitUntil(() => form.querySelector('span.error'));
expect(error.textContent).toBe('Incorrect current password');

// No IQ stanzas should have been sent
const sent_IQs = _converse.api.connection.get().IQ_stanzas;
const register_iqs = sent_IQs.filter(iq => iq.querySelector('query[xmlns="jabber:iq:register"]'));
expect(register_iqs.length).toBe(0);
})
);

it(
'allows you to reset your password',
mock.initConverse([], {}, async function (_converse) {
Expand Down
Loading