Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 01e7116

Browse files
Luke Barnarddbkr
authored andcommitted
Ask for email address after setting password for the first time
So that the user can reset their password.
1 parent 918efe5 commit 01e7116

File tree

3 files changed

+193
-3
lines changed

3 files changed

+193
-3
lines changed

src/Modal.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ const AsyncWrapper = React.createClass({
6464

6565
render: function() {
6666
const {loader, ...otherProps} = this.props;
67-
6867
if (this.state.component) {
6968
const Component = this.state.component;
7069
return <Component {...otherProps} />;
@@ -199,4 +198,7 @@ class ModalManager {
199198
}
200199
}
201200

202-
export default new ModalManager();
201+
if (!global.singletonModalManager) {
202+
global.singletonModalManager = new ModalManager();
203+
}
204+
export default global.singletonModalManager;
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*
2+
Copyright 2017 Vector Creations Ltd
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import q from 'q';
18+
import React from 'react';
19+
import sdk from '../../../index';
20+
import MatrixClientPeg from '../../../MatrixClientPeg';
21+
import classnames from 'classnames';
22+
import KeyCode from '../../../KeyCode';
23+
import Email from '../../../email';
24+
import AddThreepid from '../../../AddThreepid';
25+
import { _t, _tJsx } from '../../../languageHandler';
26+
import Modal from '../../../Modal';
27+
28+
29+
/**
30+
* Prompt the user to set an email address.
31+
*
32+
* On success, `onFinished(true)` is called.
33+
*/
34+
export default React.createClass({
35+
displayName: 'SetEmailDialog',
36+
propTypes: {
37+
onFinished: React.PropTypes.func.isRequired,
38+
},
39+
40+
getInitialState: function() {
41+
return {
42+
emailAddress: null,
43+
emailBusy: false,
44+
};
45+
},
46+
47+
componentDidMount: function() {
48+
},
49+
50+
onEmailAddressChanged: function(value) {
51+
this.setState({
52+
emailAddress: value,
53+
});
54+
},
55+
56+
onSubmit: function() {
57+
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
58+
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
59+
60+
const emailAddress = this.state.emailAddress;
61+
if (!Email.looksValid(emailAddress)) {
62+
Modal.createDialog(ErrorDialog, {
63+
title: _t("Invalid Email Address"),
64+
description: _t("This doesn't appear to be a valid email address"),
65+
});
66+
return;
67+
}
68+
this._addThreepid = new AddThreepid();
69+
// we always bind emails when registering, so let's do the
70+
// same here.
71+
this._addThreepid.addEmailAddress(emailAddress, true).done(() => {
72+
Modal.createDialog(QuestionDialog, {
73+
title: _t("Verification Pending"),
74+
description: _t(
75+
"Please check your email and click on the link it contains. Once this " +
76+
"is done, click continue.",
77+
),
78+
button: _t('Continue'),
79+
onFinished: this.onEmailDialogFinished,
80+
});
81+
}, (err) => {
82+
this.setState({emailBusy: false});
83+
console.error("Unable to add email address " + emailAddress + " " + err);
84+
Modal.createDialog(ErrorDialog, {
85+
title: _t("Unable to add email address"),
86+
description: ((err && err.message) ? err.message : _t("Operation failed")),
87+
});
88+
});
89+
this.setState({emailBusy: true});
90+
},
91+
92+
onEmailDialogFinished: function(ok) {
93+
if (ok) {
94+
this.verifyEmailAddress();
95+
} else {
96+
this.setState({emailBusy: false});
97+
}
98+
},
99+
100+
verifyEmailAddress: function() {
101+
this._addThreepid.checkEmailLinkClicked().done(() => {
102+
this.props.onFinished(true);
103+
}, (err) => {
104+
this.setState({emailBusy: false});
105+
if (err.errcode == 'M_THREEPID_AUTH_FAILED') {
106+
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
107+
const message = _t("Unable to verify email address.") + " " +
108+
_t("Please check your email and click on the link it contains. Once this is done, click continue.");
109+
Modal.createDialog(QuestionDialog, {
110+
title: _t("Verification Pending"),
111+
description: message,
112+
button: _t('Continue'),
113+
onFinished: this.onEmailDialogFinished,
114+
});
115+
} else {
116+
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
117+
console.error("Unable to verify email address: " + err);
118+
Modal.createDialog(ErrorDialog, {
119+
title: _t("Unable to verify email address."),
120+
description: ((err && err.message) ? err.message : _t("Operation failed")),
121+
});
122+
}
123+
});
124+
},
125+
126+
render: function() {
127+
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
128+
const Spinner = sdk.getComponent('elements.Spinner');
129+
const EditableText = sdk.getComponent('elements.EditableText');
130+
131+
const emailInput = this.state.emailBusy ? <Spinner /> : <EditableText
132+
className="mx_SetEmailDialog_email_input"
133+
placeholder={ _t("Email address") }
134+
placeholderClassName="mx_SetEmailDialog_email_input_placeholder"
135+
blurToCancel={ false }
136+
onValueChanged={ this.onEmailAddressChanged } />;
137+
138+
return (
139+
<BaseDialog className="mx_SetEmailDialog"
140+
onFinished={this.props.onFinished}
141+
title={this.props.title}
142+
>
143+
<div className="mx_Dialog_content">
144+
<p>
145+
{ _t('This will allow you to reset your password and receive notifications.') }
146+
</p>
147+
{ emailInput }
148+
</div>
149+
<div className="mx_Dialog_buttons">
150+
<input className="mx_Dialog_primary"
151+
type="submit"
152+
value={_t("Continue")}
153+
onClick={this.onSubmit}
154+
/>
155+
<input
156+
type="submit"
157+
value={_t("Cancel")}
158+
onClick={this.props.onFinished}
159+
/>
160+
</div>
161+
</BaseDialog>
162+
);
163+
},
164+
});

src/components/views/settings/ChangePassword.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ var React = require('react');
2020
var MatrixClientPeg = require("../../../MatrixClientPeg");
2121
var Modal = require("../../../Modal");
2222
var sdk = require("../../../index");
23+
24+
import q from 'q';
2325
import AccessibleButton from '../elements/AccessibleButton';
2426
import { _t } from '../../../languageHandler';
2527

@@ -140,7 +142,15 @@ module.exports = React.createClass({
140142
});
141143

142144
cli.setPassword(authDict, newPassword).then(() => {
143-
this.props.onFinished();
145+
if (this.props.shouldAskForEmail) {
146+
return this._optionallySetEmail().then((confirmed) => {
147+
this.props.onFinished({
148+
didSetEmail: confirmed,
149+
});
150+
});
151+
} else {
152+
this.props.onFinished();
153+
}
144154
}, (err) => {
145155
this.props.onError(err);
146156
}).finally(() => {
@@ -150,6 +160,20 @@ module.exports = React.createClass({
150160
}).done();
151161
},
152162

163+
_optionallySetEmail: function() {
164+
const deferred = q.defer();
165+
// Ask for an email otherwise the user has no way to reset their password
166+
const SetEmailDialog = sdk.getComponent("dialogs.SetEmailDialog");
167+
Modal.createDialog(SetEmailDialog, {
168+
title: _t('Do you want to set an email address?'),
169+
onFinished: (confirmed) => {
170+
// ignore confirmed, setting an email is optional
171+
deferred.resolve(confirmed);
172+
},
173+
});
174+
return deferred.promise;
175+
},
176+
153177
_onExportE2eKeysClicked: function() {
154178
Modal.createDialogAsync(
155179
(cb) => {

0 commit comments

Comments
 (0)