Skip to content

Commit 0aecf57

Browse files
JulianAdams4not-gabriel
authored andcommitted
Forgot password (#401)
* Check username before enter password on Login * Forgot password on Login
1 parent 00b0bc5 commit 0aecf57

File tree

13 files changed

+274
-132
lines changed

13 files changed

+274
-132
lines changed

electron_app/src/clientManager.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ class ClientManager {
153153
return checkDeviceRemoved(res);
154154
}
155155

156+
async resetPassword(recipientId) {
157+
const res = await client.resetPassword(recipientId);
158+
return checkDeviceRemoved(res);
159+
}
160+
156161
async unlockDevice(params) {
157162
const res = await client.unlockDevice(params);
158163
return checkDeviceRemoved(res);

email_dialog/src/components/Dialog.js

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,27 @@ import { remoteData, onResponseModal } from './../utils/electronInterface';
33
import * as messages from './../utils/contents';
44
import './dialog.css';
55

6-
const { title, contentType, options, sendTo } = remoteData;
6+
const { title, contentType, options, sendTo, customTextToReplace } = remoteData;
77

88
const Dialog = () => (
99
<div className="dialog-body">
1010
<div className="header" />
1111
<div className="content">
1212
<h2 className="title">{title}</h2>
13-
{renderContent(contentType)}
13+
{renderContent(customTextToReplace, contentType)}
1414
{renderOptions(options, sendTo)}
1515
</div>
1616
</div>
1717
);
1818

19-
const renderContent = contentType => {
19+
const renderContent = (customText, contentType) => {
2020
switch (contentType) {
2121
case 'EMPTY_RECOVERY_EMAIL':
2222
return messages.EmptyRecoveryEmail();
23-
case 'FORGOT_PASSWORD_SENT_LINK':
24-
return messages.ForgotPasswordSentLink();
23+
case 'FORGOT_PASSWORD_SEND_LINK':
24+
return messages.ForgotPasswordSentLink(customText);
2525
case 'FORGOT_PASSWORD_EMPTY_EMAIL':
26-
return messages.ForgotPasswordEmptyEmail();
26+
return messages.ForgotPasswordEmptyEmail(customText);
2727
case 'PERMANENT_DELETE_THREAD':
2828
return messages.PermanentDeleteThread();
2929
default:
@@ -34,18 +34,22 @@ const renderContent = contentType => {
3434
const renderOptions = (options, sendTo) => {
3535
return (
3636
<div className="options">
37-
<button
38-
className={options.acceptLabel !== '' ? 'cancel' : 'hidden'}
39-
onClick={e => onResponseModal(e, options.cancelLabel, sendTo)}
40-
>
41-
<span>{options.cancelLabel}</span>
42-
</button>
43-
<button
44-
className={options.acceptLabel !== '' ? 'confirm' : 'hidden'}
45-
onClick={e => onResponseModal(e, options.acceptLabel, sendTo)}
46-
>
47-
<span>{options.acceptLabel}</span>
48-
</button>
37+
{options.cancelLabel && (
38+
<button
39+
className="cancel"
40+
onClick={e => onResponseModal(e, options.cancelLabel, sendTo)}
41+
>
42+
<span>{options.cancelLabel}</span>
43+
</button>
44+
)}
45+
{options.acceptLabel && (
46+
<button
47+
className="confirm"
48+
onClick={e => onResponseModal(e, options.acceptLabel, sendTo)}
49+
>
50+
<span>{options.acceptLabel}</span>
51+
</button>
52+
)}
4953
</div>
5054
);
5155
};

email_dialog/src/components/dialog.scss

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
}
3131

3232
.message-empty-recovery-email {
33-
font-size: 13px;
33+
font-size: 13.5px;
3434
position: relative;
3535
top: 10px;
3636
}
@@ -40,7 +40,7 @@
4040
top: 15px;
4141
}
4242
.message-forgot-sent-link {
43-
font-size: 14px;
43+
font-size: 15px;
4444
position: relative;
4545
top: 20px;
4646
p {
@@ -62,6 +62,9 @@
6262
position: absolute;
6363
bottom: 30px;
6464
.cancel {
65+
position: absolute;
66+
left: 5px;
67+
bottom: 0px;
6568
border: none;
6669
outline: none;
6770
border-radius: 100px;
@@ -77,6 +80,9 @@
7780
}
7881
}
7982
.confirm {
83+
position: absolute;
84+
left: 190px;
85+
bottom: 0px;
8086
border: none;
8187
outline: none;
8288
border-radius: 100px;

email_dialog/src/utils/contents.js

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,33 @@ export const LostAllDevices = () => (
99
</div>
1010
);
1111

12-
export const EmptyRecoveryEmail = () => (
13-
<div className="message-empty-recovery-email">
14-
<p>
15-
You did not set a <strong>Recovery Email</strong> so account recovery is
16-
impossible if you forget your password.
17-
</p>
18-
<p>Proceed without recovery email?</p>
19-
</div>
20-
);
12+
export const EmptyRecoveryEmail = () => {
13+
return (
14+
<div className="message-empty-recovery-email">
15+
<p>
16+
You did not set a <strong>Recovery Email</strong> so account recovery is
17+
impossible if you forget your password.
18+
</p>
19+
</div>
20+
);
21+
};
2122

22-
export const ForgotPasswordSentLink = () => (
23-
<div className="message-forgot-sent-link">
24-
<p>A reset link will be sent to d******@o****l.com</p>
25-
<p>The link will be valid for 1 hour</p>
26-
</div>
27-
);
23+
export const ForgotPasswordSentLink = customText => {
24+
const content =
25+
customText ||
26+
`A reset link was sent to your Recovery email\nThe link will be valid for 30 min`;
27+
return (
28+
<div className="message-forgot-sent-link">
29+
<p>{content}</p>
30+
</div>
31+
);
32+
};
2833

29-
export const ForgotPasswordEmptyEmail = () => (
34+
export const ForgotPasswordEmptyEmail = customText => (
3035
<div className="message-forgot-empty-email">
31-
<p>You need to set a Recovery Email to reset your password.</p>
36+
<p>
37+
{customText || `You need to set a Recovery Email to reset your password`}
38+
</p>
3239
</div>
3340
);
3441

email_login/src/components/Login.js

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,18 @@ const renderForm = props => (
2727
<div className="form">
2828
<form autoComplete="off">
2929
<div className="label">
30-
<label>
31-
<input
32-
type="text"
33-
name="username"
34-
placeholder="Username"
35-
value={props.value}
36-
onChange={props.onChangeField}
37-
onKeyUp={props.validator}
38-
autoFocus={true}
39-
/>
40-
&nbsp;
41-
<span>@criptext.com</span>
42-
<div className="clear" />
43-
</label>
30+
<input
31+
type="text"
32+
name="username"
33+
placeholder="Username"
34+
value={props.value}
35+
onChange={props.onChangeField}
36+
autoFocus={true}
37+
/>
38+
&nbsp;
39+
<span>@criptext.com</span>
4440
</div>
41+
<span className="error-message">{props.errorMessage}</span>
4542
<div className="button">
4643
<button
4744
className="button-login"
@@ -67,10 +64,10 @@ const renderFooter = props => (
6764
);
6865

6966
renderForm.propTypes = {
67+
disabled: PropTypes.bool,
68+
errorMessage: PropTypes.string,
7069
onChangeField: PropTypes.func,
71-
validator: PropTypes.func,
7270
onClickSignIn: PropTypes.func,
73-
disabled: PropTypes.bool,
7471
value: PropTypes.string
7572
};
7673

email_login/src/components/LoginWrapper.js

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import SignUpWrapper from './SignUpWrapper';
44
import LostAllDevicesWrapper from './LostAllDevicesWrapper';
55
import ContinueLogin from './ContinueLogin';
66
import { closeDialog, confirmLostDevices } from './../utils/electronInterface';
7-
import { validateUsername } from './../validators/validators';
7+
import {
8+
validateUsername,
9+
checkUsernameAvailable
10+
} from './../validators/validators';
811

912
const mode = {
1013
SIGNUP: 'SIGNUP',
@@ -13,6 +16,10 @@ const mode = {
1316
LOST_DEVICES: 'LOST_DEVICES'
1417
};
1518

19+
const errorMessages = {
20+
USERNAME_NOT_EXISTS: "Username doesn't exists"
21+
};
22+
1623
class LoginWrapper extends Component {
1724
constructor() {
1825
super();
@@ -21,13 +28,14 @@ class LoginWrapper extends Component {
2128
values: {
2229
username: ''
2330
},
24-
disabled: true
31+
disabled: true,
32+
errorMessage: ''
2533
};
2634
this.timeCountdown = 0;
2735
}
2836

29-
componentDidMount() {
30-
this.checkDisable();
37+
async componentDidMount() {
38+
await this.checkDisable();
3139
}
3240

3341
render() {
@@ -55,9 +63,9 @@ class LoginWrapper extends Component {
5563
onClickSignIn={this.handleClickSignIn}
5664
onChangeField={this.handleChange}
5765
disabled={this.state.disabled}
58-
validator={this.validateUsername}
5966
value={this.state.values.username}
6067
handleLostDevices={this.handleLostDevices}
68+
errorMessage={this.state.errorMessage}
6169
/>
6270
);
6371
}
@@ -66,42 +74,47 @@ class LoginWrapper extends Component {
6674
toggleSignUp = ev => {
6775
ev.preventDefault();
6876
ev.stopPropagation();
69-
this.setState({
70-
mode: this.state.mode === mode.LOGIN ? mode.SIGNUP : mode.LOGIN
77+
const nextMode = this.state.mode === mode.LOGIN ? mode.SIGNUP : mode.LOGIN;
78+
this.setState({ mode: nextMode }, async () => {
79+
await this.checkDisable();
7180
});
72-
this.checkDisable();
7381
};
7482

7583
toggleContinue = ev => {
7684
ev.preventDefault();
7785
ev.stopPropagation();
7886
this.stopCountdown();
79-
this.setState({
80-
mode: this.state.mode === mode.LOGIN ? mode.CONTINUE : mode.LOGIN
87+
const nextMode =
88+
this.state.mode === mode.LOGIN ? mode.CONTINUE : mode.LOGIN;
89+
this.setState({ mode: nextMode }, async () => {
90+
await this.checkDisable();
8191
});
82-
this.checkDisable();
8392
};
8493

8594
toggleLostAllDevices = ev => {
8695
ev.preventDefault();
8796
ev.stopPropagation();
88-
this.setState({
89-
mode: mode.LOGIN
90-
});
91-
this.checkDisable();
97+
this.setState(
98+
{
99+
mode: mode.LOGIN
100+
},
101+
async () => {
102+
await this.checkDisable();
103+
}
104+
);
92105
};
93106

94107
stopCountdown = () => {
95108
clearTimeout(this.timeCountdown);
96109
};
97110

98-
validateUsername = () => {
111+
validateUsername = async () => {
99112
const username = this.state.values['username'];
100-
return validateUsername(username);
113+
return await validateUsername(username);
101114
};
102115

103-
checkDisable = () => {
104-
const isValid = this.validateUsername();
116+
checkDisable = async () => {
117+
const isValid = await this.validateUsername();
105118
this.setState({
106119
disabled: !isValid
107120
});
@@ -110,17 +123,26 @@ class LoginWrapper extends Component {
110123
handleChange = event => {
111124
const values = { ...this.state.values };
112125
values[event.target.name] = event.target.value;
113-
this.setState({ values }, () => {
114-
this.checkDisable();
126+
this.setState({ values, errorMessage: '' }, async () => {
127+
await this.checkDisable();
115128
});
116129
};
117130

118-
handleClickSignIn = event => {
119-
event.preventDefault();
120-
event.stopPropagation();
121-
this.setState({
122-
mode: mode.LOST_DEVICES
123-
});
131+
handleClickSignIn = async ev => {
132+
ev.preventDefault();
133+
ev.stopPropagation();
134+
const isAvailable = await checkUsernameAvailable(
135+
this.state.values.username
136+
);
137+
if (isAvailable) {
138+
this.setState({
139+
errorMessage: errorMessages.USERNAME_NOT_EXISTS
140+
});
141+
} else {
142+
this.setState({
143+
mode: mode.LOST_DEVICES
144+
});
145+
}
124146
};
125147

126148
handleLostDevices = event => {

email_login/src/components/LostAllDevices.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ const renderForm = props => (
4949
placeholder="Password"
5050
value={props.values.password}
5151
onChange={props.onChangeField}
52-
onKeyUp={props.validator}
5352
disabled={props.isLoading}
5453
autoFocus={true}
5554
/>

0 commit comments

Comments
 (0)