Merge pull request #181 from grant-project/resend-verification
Resend email verification
This commit is contained in:
commit
7215e416a1
|
@ -156,10 +156,7 @@ class User(db.Model, UserMixin):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
if _send_email:
|
if _send_email:
|
||||||
send_email(user.email_address, 'signup', {
|
user.send_verification_email()
|
||||||
'display_name': user.display_name,
|
|
||||||
'confirm_url': make_url(f'/email/verify?code={ev.code}')
|
|
||||||
})
|
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
@ -212,6 +209,12 @@ class User(db.Model, UserMixin):
|
||||||
def login(self):
|
def login(self):
|
||||||
login_user(self)
|
login_user(self)
|
||||||
|
|
||||||
|
def send_verification_email(self):
|
||||||
|
send_email(self.email_address, 'signup', {
|
||||||
|
'display_name': self.display_name,
|
||||||
|
'confirm_url': make_url(f'/email/verify?code={self.email_verification.code}')
|
||||||
|
})
|
||||||
|
|
||||||
def send_recovery_email(self):
|
def send_recovery_email(self):
|
||||||
existing = self.email_recovery
|
existing = self.email_recovery
|
||||||
if existing:
|
if existing:
|
||||||
|
|
|
@ -170,11 +170,18 @@ def update_user_password(current_password, password):
|
||||||
def update_user_email(email, password):
|
def update_user_email(email, password):
|
||||||
if not g.current_user.check_password(password):
|
if not g.current_user.check_password(password):
|
||||||
return {"message": "Password is incorrect"}, 403
|
return {"message": "Password is incorrect"}, 403
|
||||||
print('set_email')
|
|
||||||
g.current_user.set_email(email)
|
g.current_user.set_email(email)
|
||||||
return None, 200
|
return None, 200
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/me/resend-verification", methods=["PUT"])
|
||||||
|
@requires_auth
|
||||||
|
@endpoint.api()
|
||||||
|
def resend_email_verification():
|
||||||
|
g.current_user.send_verification_email()
|
||||||
|
return None, 200
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route("/logout", methods=["POST"])
|
@blueprint.route("/logout", methods=["POST"])
|
||||||
@requires_auth
|
@requires_auth
|
||||||
@endpoint.api()
|
@endpoint.api()
|
||||||
|
|
|
@ -294,3 +294,7 @@ export function getRFP(rfpId: number | string): Promise<{ data: RFP }> {
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resendEmailVerification(): Promise<{ data: void }> {
|
||||||
|
return axios.put(`/api/v1/users/me/resend-verification`);
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
.AccountSettings {
|
.AccountSettings {
|
||||||
&-form {
|
&-form {
|
||||||
|
&-resend {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
& > .ant-form-item {
|
& > .ant-form-item {
|
||||||
margin-bottom: 0.75rem;
|
margin-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Form, Input, Button, Alert } from 'antd';
|
import { Form, Input, Button, Alert, message } from 'antd';
|
||||||
import { FormComponentProps } from 'antd/lib/form';
|
import { FormComponentProps } from 'antd/lib/form';
|
||||||
import { updateUserEmail } from 'api/api';
|
import Loader from 'components/Loader';
|
||||||
|
import { updateUserEmail, resendEmailVerification } from 'api/api';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import './Account.less';
|
import './Account.less';
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
email: string;
|
email: string;
|
||||||
|
emailVerified: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = FormComponentProps & StateProps;
|
type Props = FormComponentProps & StateProps;
|
||||||
|
@ -17,6 +19,8 @@ const STATE = {
|
||||||
emailChangePending: false,
|
emailChangePending: false,
|
||||||
emailChangeSuccess: false,
|
emailChangeSuccess: false,
|
||||||
emailChangeError: '',
|
emailChangeError: '',
|
||||||
|
isResendingVerification: false,
|
||||||
|
hasResentVerification: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = typeof STATE;
|
type State = typeof STATE;
|
||||||
|
@ -25,12 +29,14 @@ class AccountSettings extends React.Component<Props, State> {
|
||||||
state: State = { ...STATE };
|
state: State = { ...STATE };
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { email, form } = this.props;
|
const { email, emailVerified, form } = this.props;
|
||||||
const {
|
const {
|
||||||
emailChangeError,
|
emailChangeError,
|
||||||
emailChangePending,
|
emailChangePending,
|
||||||
emailChangeSuccess,
|
emailChangeSuccess,
|
||||||
newEmail,
|
newEmail,
|
||||||
|
isResendingVerification,
|
||||||
|
hasResentVerification,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -40,6 +46,36 @@ class AccountSettings extends React.Component<Props, State> {
|
||||||
onSubmit={this.handleSubmit}
|
onSubmit={this.handleSubmit}
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
>
|
>
|
||||||
|
{!emailVerified &&
|
||||||
|
!hasResentVerification && (
|
||||||
|
<Alert
|
||||||
|
showIcon
|
||||||
|
className="AccountSettings-form-resend"
|
||||||
|
type="warning"
|
||||||
|
message="Your email has not been verified"
|
||||||
|
description={
|
||||||
|
<>
|
||||||
|
You should have a verification in your inbox. If you can't find it,
|
||||||
|
check your spam folder. Still don't see it?{' '}
|
||||||
|
<a onClick={this.resendEmailVerification}>Click here to resend</a>.
|
||||||
|
{isResendingVerification && <Loader overlay />}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!emailVerified &&
|
||||||
|
hasResentVerification && (
|
||||||
|
<Alert
|
||||||
|
showIcon
|
||||||
|
className="AccountSettings-form-resend"
|
||||||
|
type="success"
|
||||||
|
message="Verification has been sent"
|
||||||
|
description={`
|
||||||
|
It should be in your inbox shortly. If you don’t see it soon,
|
||||||
|
check your spam folder or contact support for help.
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Form.Item label="Email">
|
<Form.Item label="Email">
|
||||||
{form.getFieldDecorator('email', {
|
{form.getFieldDecorator('email', {
|
||||||
initialValue: newEmail || email,
|
initialValue: newEmail || email,
|
||||||
|
@ -139,10 +175,25 @@ class AccountSettings extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private resendEmailVerification = async () => {
|
||||||
|
if (this.state.isResendingVerification) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.setState({ isResendingVerification: true });
|
||||||
|
try {
|
||||||
|
await resendEmailVerification();
|
||||||
|
this.setState({ hasResentVerification: true });
|
||||||
|
} catch (err) {
|
||||||
|
message.error(err.message || err.toString());
|
||||||
|
}
|
||||||
|
this.setState({ isResendingVerification: false });
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const FormWrappedAccountSettings = Form.create()(AccountSettings);
|
const FormWrappedAccountSettings = Form.create()(AccountSettings);
|
||||||
|
|
||||||
export default connect<StateProps, {}, {}, AppState>(state => ({
|
export default connect<StateProps, {}, {}, AppState>(state => ({
|
||||||
email: state.auth.user ? state.auth.user.emailAddress || '' : '',
|
email: state.auth.user ? state.auth.user.emailAddress || '' : '',
|
||||||
|
emailVerified: !!state.auth.user && !!state.auth.user.emailVerified,
|
||||||
}))(FormWrappedAccountSettings);
|
}))(FormWrappedAccountSettings);
|
||||||
|
|
Loading…
Reference in New Issue