Add confirmation email

This commit is contained in:
Jim LAURIE 2018-08-08 17:57:02 +02:00
parent f15202b306
commit eec423a2cd
8 changed files with 135 additions and 7 deletions

View File

@ -34,7 +34,7 @@ class EditForm extends React.Component { // eslint-disable-line react/prefer-sta
</div>
);
}
return (
<div className={styles.editForm}>
<div className="row">
@ -97,6 +97,27 @@ class EditForm extends React.Component { // eslint-disable-line react/prefer-sta
value={get(this.props.values.settings, 'allow_register')}
/>
</div>
<div className={styles.separator} />
<div className="row">
<Input
label={{ id: 'users-permissions.EditForm.inputToggle.label.email-confirmation' }}
inputDescription={{ id: 'users-permissions.EditForm.inputToggle.description.email-confirmation' }}
name="advanced.settings.email_confirmation"
onChange={this.props.onChange}
type="toggle"
value={get(this.props.values.settings, 'email_confirmation')}
/>
</div>
<div className="row">
<Input
label={{ id: 'users-permissions.EditForm.inputToggle.label.email-confirmation-redirection' }}
inputDescription={{ id: 'users-permissions.EditForm.inputToggle.description.email-confirmation-redirection' }}
name="advanced.settings.email_confirmation_redirection"
onChange={this.props.onChange}
type="text"
value={get(this.props.values.settings, 'email_confirmation_redirection')}
/>
</div>
</div>
);
}

View File

@ -6,6 +6,7 @@
"Auth.form.button.login": "Log in",
"Auth.form.button.register": "Ready to start",
"Auth.form.error.noAdminAccess": "You can't access the administration panel.",
"Auth.form.error.confirmed": "Your account email is not confirmed.",
"Auth.form.forgot-password.email.label": "Enter your email",
"Auth.form.forgot-password.email.label.success": "Email successfully sent to",
@ -65,8 +66,12 @@
"EditForm.inputToggle.label.email": "One account per email address",
"EditForm.inputToggle.label.sign-up": "Enable sign-ups",
"EditForm.inputToggle.label.email-confirmation": "Enable email confirmation",
"EditForm.inputToggle.label.email-confirmation-redirection": "Redirection url",
"EditForm.inputToggle.description.email": "Disallow the user to create multiple accounts using the same email address with different authentication providers.",
"EditForm.inputToggle.description.sign-up": "When disabled (OFF), the registration process is forbidden. No one can subscribe anymore no matter the used provider.",
"EditForm.inputToggle.description.email-confirmation": "When enabled (ON), new registred users receive a confirmation email.",
"EditForm.inputToggle.description.email-confirmation-redirection": "After confirmed your email, chose where you will be redirected.",
"EditPage.cancel": "Cancel",
"EditPage.submit": "Save",
@ -129,7 +134,7 @@
"Policies.header.hint": "Select the application's actions or the plugin's actions and click on the cog icon to display the bound route",
"Policies.header.title": "Advanced settings",
"Email.template.validation_email": "Email address validation",
"Email.template.email_confirmation": "Email address confirmation",
"Email.template.reset_password": "Reset password",
"Email.template.success_register": "Registration successful",

View File

@ -117,6 +117,25 @@ module.exports = async cb => {
<p><%= URL %>?code=<%= TOKEN %></p>
<p>Thanks.</p>`
}
},
'email_confirmation': {
display: 'Email.template.email_confirmation',
icon: 'check-square-o',
options: {
from: {
name: 'Administration Panel',
email: 'no-reply@strapi.io'
},
response_email: '',
object: 'Account confirmation',
message: `<p>Thank you to register!</p>
<p>You have to confirm your email addresse. Please click on the link below.</p>
<p><%= URL %>?confirmation=<%= CODE %></p>
<p>Thanks.</p>`
}
}
@ -129,11 +148,13 @@ module.exports = async cb => {
const value = {
unique_email: true,
allow_register: true,
email_confirmation: false,
email_confirmation_redirection: `http://${strapi.config.currentEnvironment.server.host}:${strapi.config.currentEnvironment.server.port}/admin`,
default_role: 'authenticated'
};
await pluginStore.set({key: 'advanced', value});
}
strapi.plugins['users-permissions'].services.userspermissions.initialize(cb);
};

View File

@ -1,3 +1,5 @@
const _ = require('lodash');
module.exports = async (ctx, next) => {
let role;
@ -23,6 +25,16 @@ module.exports = async (ctx, next) => {
if (role.type === 'root') {
return await next();
}
const store = await strapi.store({
environment: '',
type: 'plugin',
name: 'users-permissions'
});
if (_.get(await store.get({key: 'advanced'}), 'email_confirmation') && ctx.state.user.confirmed !== true) {
return ctx.unauthorized('Your account email is not confirmed.');
}
}
// Retrieve `public` role.
if (!role) {

View File

@ -202,6 +202,15 @@
"prefix": ""
}
},
{
"method": "GET",
"path": "/auth/email-confirmation",
"handler": "Auth.emailConfirmation",
"config": {
"policies": [],
"prefix": ""
}
},
{
"method": "GET",

View File

@ -52,6 +52,10 @@ module.exports = {
// Check if the user exists.
const user = await strapi.query('user', 'users-permissions').findOne(query, ['role']);
if (_.get(await store.get({key: 'advanced'}), 'email_confirmation') && user.confirmed !== true) {
return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.form.error.confirmed' }] }] : 'Your account email is not confirmed.');
}
if (!user) {
return ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: 'Auth.form.error.invalid' }] }] : 'Identifier or password invalid.');
}
@ -281,8 +285,42 @@ module.exports = {
try {
const user = await strapi.query('user', 'users-permissions').create(params);
const jwt = strapi.plugins['users-permissions'].services.jwt.issue(_.pick(user.toJSON ? user.toJSON() : user, ['_id', 'id']));
if (settings.email_confirmation) {
const settings = (await strapi.store({
environment: '',
type: 'plugin',
name: 'users-permissions'
}).get({ key: 'email' }))['email_confirmation'].options;
settings.message = await strapi.plugins['users-permissions'].services.userspermissions.template(settings.message, {
URL: `http://${strapi.config.currentEnvironment.server.host}:${strapi.config.currentEnvironment.server.port}/auth/email-confirmation`,
USER: _.omit(user.toJSON ? user.toJSON() : user, ['password', 'resetPasswordToken', 'role', 'provider']),
CODE: jwt
});
settings.object = await strapi.plugins['users-permissions'].services.userspermissions.template(settings.object, {
USER: _.omit(user.toJSON ? user.toJSON() : user, ['password', 'resetPasswordToken', 'role', 'provider'])
});
try {
// Send an email to the user.
await strapi.plugins['email'].services.email.send({
to: user.email,
from: (settings.from.email || settings.from.name) ? `"${settings.from.name}" <${settings.from.email}>` : undefined,
replyTo: settings.response_email,
subject: settings.object,
text: settings.message,
html: settings.message
});
} catch (err) {
return ctx.badRequest(null, err);
}
}
ctx.send({
jwt: strapi.plugins['users-permissions'].services.jwt.issue(_.pick(user.toJSON ? user.toJSON() : user, ['_id', 'id'])),
jwt,
user: _.omit(user.toJSON ? user.toJSON() : user, ['password', 'resetPasswordToken'])
});
} catch(err) {
@ -290,5 +328,22 @@ module.exports = {
ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: adminError }] }] : err.message);
}
},
emailConfirmation: async (ctx) => {
const params = ctx.query;
const user = await strapi.plugins['users-permissions'].services.jwt.verify(params.confirmation);
await strapi.plugins['users-permissions'].services.user.edit(_.pick(user, ['_id', 'id']), {confirmed: true});
const settings = await strapi.store({
environment: '',
type: 'plugin',
name: 'users-permissions',
key: 'advanced'
}).get();
ctx.redirect(settings.email_confirmation_redirection);
}
};

View File

@ -33,6 +33,10 @@
"configurable": false,
"private": true
},
"confirmed": {
"type": "boolean",
"configurable": false
},
"role": {
"model": "role",
"via": "users",
@ -40,4 +44,4 @@
"configurable": false
}
}
}
}

View File

@ -251,13 +251,14 @@ module.exports = {
const defaultPolicy = (obj, role) => {
const isCallback = obj.action === 'callback' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'public';
const isConnect = obj.action === 'connect' && obj.controller === 'auth' && obj.type === 'users-permissions';
const isRegister = obj.action === 'register' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'public';
const isPassword = obj.action === 'forgotpassword' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'public';
const isRegister = obj.action === 'register' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'public';
const isConfirmation = obj.action === 'emailconfirmation' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'public';
const isNewPassword = obj.action === 'changepassword' && obj.controller === 'auth' && obj.type === 'users-permissions' && role.type === 'public';
const isInit = obj.action === 'init' && obj.controller === 'userspermissions';
const isMe = obj.action === 'me' && obj.controller === 'user' && obj.type === 'users-permissions';
const isReload = obj.action === 'autoreload';
const enabled = isCallback || isRegister || role.type === 'root' || isInit || isPassword || isNewPassword || isMe || isReload || isConnect;
const enabled = isCallback || isRegister || role.type === 'root' || isInit || isPassword || isNewPassword || isMe || isReload || isConnect || isConfirmation;
return Object.assign(obj, { enabled, policy: '' });
};