2019-04-09 12:09:03 +02:00
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Auth.js controller
|
|
|
|
|
*
|
|
|
|
|
* @description: A set of functions called "actions" for managing `Auth`.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* eslint-disable no-useless-escape */
|
|
|
|
|
const crypto = require('crypto');
|
|
|
|
|
const _ = require('lodash');
|
|
|
|
|
|
|
|
|
|
const emailRegExp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
2019-08-21 12:10:23 +02:00
|
|
|
|
const formatError = error => [
|
|
|
|
|
{ messages: [{ id: error.id, message: error.message, field: error.field }] },
|
|
|
|
|
];
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
2020-05-13 18:16:12 +02:00
|
|
|
|
// this is a temp patch for the next dev
|
|
|
|
|
const createUser = params => ({
|
|
|
|
|
...params,
|
|
|
|
|
isActive: true,
|
|
|
|
|
firstname: null,
|
|
|
|
|
lastname: null,
|
|
|
|
|
});
|
|
|
|
|
|
2019-04-09 12:09:03 +02:00
|
|
|
|
module.exports = {
|
2019-07-15 19:33:07 +02:00
|
|
|
|
async register(ctx) {
|
2019-04-09 12:09:03 +02:00
|
|
|
|
const params = ctx.request.body;
|
|
|
|
|
|
|
|
|
|
// Username is required.
|
|
|
|
|
if (!params.username) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
2019-08-21 12:10:23 +02:00
|
|
|
|
formatError({
|
|
|
|
|
id: 'Auth.form.error.username.provide',
|
|
|
|
|
message: 'Please provide your username.',
|
|
|
|
|
})
|
2019-04-09 12:09:03 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Email is required.
|
|
|
|
|
if (!params.email) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
2019-08-21 12:10:23 +02:00
|
|
|
|
formatError({
|
|
|
|
|
id: 'Auth.form.error.email.provide',
|
|
|
|
|
message: 'Please provide your email.',
|
|
|
|
|
})
|
2019-04-09 12:09:03 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-24 14:05:25 +02:00
|
|
|
|
// Check if the provided email is valid or not.
|
|
|
|
|
const isEmail = emailRegExp.test(params.email);
|
|
|
|
|
|
|
|
|
|
if (isEmail) {
|
|
|
|
|
params.email = params.email.toLowerCase();
|
|
|
|
|
} else {
|
|
|
|
|
return ctx.badRequest('Invalid email format');
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-09 12:09:03 +02:00
|
|
|
|
// Password is required.
|
|
|
|
|
if (!params.password) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
2019-08-21 12:10:23 +02:00
|
|
|
|
formatError({
|
|
|
|
|
id: 'Auth.form.error.password.provide',
|
|
|
|
|
message: 'Please provide your password.',
|
|
|
|
|
})
|
2019-04-09 12:09:03 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-24 14:05:25 +02:00
|
|
|
|
// First, check if their is at least one admin
|
2020-05-12 16:38:48 +02:00
|
|
|
|
const admins = await strapi.query('user', 'admin').find({ _limit: 1 });
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
2019-05-24 14:05:25 +02:00
|
|
|
|
if (admins.length > 0) {
|
2019-04-09 12:09:03 +02:00
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
2019-08-21 12:10:23 +02:00
|
|
|
|
formatError({
|
|
|
|
|
id: 'Auth.form.error.admin.exist',
|
|
|
|
|
message: "You can't register a new admin",
|
|
|
|
|
})
|
2019-04-09 12:09:03 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-25 20:02:29 +01:00
|
|
|
|
params.password = await strapi.admin.services.auth.hashPassword(params.password);
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
2020-05-12 16:38:48 +02:00
|
|
|
|
const admin = await strapi.query('user', 'admin').findOne({
|
2019-04-09 12:09:03 +02:00
|
|
|
|
email: params.email,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (admin) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
2019-08-21 12:10:23 +02:00
|
|
|
|
formatError({
|
|
|
|
|
id: 'Auth.form.error.email.taken',
|
|
|
|
|
message: 'Email is already taken',
|
|
|
|
|
})
|
2019-04-09 12:09:03 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
2020-05-13 18:16:12 +02:00
|
|
|
|
const admin = await strapi.query('user', 'admin').create(createUser(params));
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
|
|
|
|
admin.isAdmin = true;
|
|
|
|
|
|
2020-05-14 11:58:36 +02:00
|
|
|
|
const jwt = strapi.admin.services.token.createJwtToken(admin);
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
2020-03-25 20:02:29 +01:00
|
|
|
|
await strapi.telemetry.send('didCreateFirstAdmin');
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
|
|
|
|
ctx.send({
|
|
|
|
|
jwt,
|
2020-05-14 11:58:36 +02:00
|
|
|
|
user: strapi.admin.services.user.sanitizeUser(admin),
|
2019-04-09 12:09:03 +02:00
|
|
|
|
});
|
|
|
|
|
} catch (err) {
|
2019-04-16 09:35:13 +02:00
|
|
|
|
strapi.log.error(err);
|
2019-04-09 12:09:03 +02:00
|
|
|
|
const adminError = _.includes(err.message, 'username')
|
2019-08-21 12:10:23 +02:00
|
|
|
|
? {
|
|
|
|
|
id: 'Auth.form.error.username.taken',
|
|
|
|
|
message: 'Username already taken',
|
|
|
|
|
}
|
|
|
|
|
: { id: 'Auth.form.error.email.taken', message: 'Email already taken' };
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
2019-08-21 12:10:23 +02:00
|
|
|
|
ctx.badRequest(null, formatError(adminError));
|
2019-04-09 12:09:03 +02:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2020-03-30 15:13:27 -04:00
|
|
|
|
async resetPassword(ctx) {
|
2019-07-15 19:33:07 +02:00
|
|
|
|
const { password, passwordConfirmation, code } = {
|
|
|
|
|
...ctx.request.body,
|
|
|
|
|
...ctx.params,
|
|
|
|
|
};
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
2019-08-21 12:10:23 +02:00
|
|
|
|
if (!password) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
|
|
|
|
formatError({
|
|
|
|
|
id: 'missing.password',
|
|
|
|
|
message: 'Missing password',
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!passwordConfirmation) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
formatError({
|
|
|
|
|
id: 'missing.passwordConfirmation',
|
|
|
|
|
message: 'Missing passwordConfirmation',
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!code) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
|
|
|
|
formatError({
|
|
|
|
|
id: 'missing.code',
|
|
|
|
|
message: 'Missing code',
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
2019-07-15 19:33:07 +02:00
|
|
|
|
if (password !== passwordConfirmation) {
|
2019-04-09 12:09:03 +02:00
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
2019-08-21 12:10:23 +02:00
|
|
|
|
formatError({
|
|
|
|
|
id: 'Auth.form.error.password.matching',
|
|
|
|
|
message: 'Passwords do not match.',
|
|
|
|
|
})
|
2019-04-09 12:09:03 +02:00
|
|
|
|
);
|
2019-07-15 19:33:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-12 16:38:48 +02:00
|
|
|
|
const admin = await strapi.query('user', 'admin').findOne({ resetPasswordToken: `${code}` });
|
2019-07-15 19:33:07 +02:00
|
|
|
|
|
|
|
|
|
if (!admin) {
|
2019-04-09 12:09:03 +02:00
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
2019-08-21 12:10:23 +02:00
|
|
|
|
formatError({
|
|
|
|
|
id: 'Auth.form.error.code.provide',
|
|
|
|
|
message: 'Incorrect code provided.',
|
|
|
|
|
})
|
2019-04-09 12:09:03 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
2019-07-15 19:33:07 +02:00
|
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
|
resetPasswordToken: null,
|
|
|
|
|
password: await strapi.admin.services.auth.hashPassword(password),
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-12 16:38:48 +02:00
|
|
|
|
const updatedAdmin = await strapi.query('user', 'admin').update({ id: admin.id }, data);
|
2019-07-15 19:33:07 +02:00
|
|
|
|
|
|
|
|
|
return ctx.send({
|
|
|
|
|
jwt: strapi.admin.services.auth.createJwtToken(updatedAdmin),
|
|
|
|
|
user: strapi.admin.services.auth.sanitizeUser(updatedAdmin),
|
|
|
|
|
});
|
2019-04-09 12:09:03 +02:00
|
|
|
|
},
|
|
|
|
|
|
2019-07-15 19:33:07 +02:00
|
|
|
|
async forgotPassword(ctx) {
|
2019-04-09 12:09:03 +02:00
|
|
|
|
const { email, url } = ctx.request.body;
|
|
|
|
|
|
2019-08-21 12:10:23 +02:00
|
|
|
|
if (!email) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
|
|
|
|
formatError({
|
|
|
|
|
id: 'missing.email',
|
|
|
|
|
message: 'Missing email',
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if (!url) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
|
|
|
|
formatError({
|
|
|
|
|
id: 'missing.url',
|
|
|
|
|
message: 'Missing url',
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-07-15 19:33:07 +02:00
|
|
|
|
|
2019-04-09 12:09:03 +02:00
|
|
|
|
// Find the admin thanks to his email.
|
2020-05-12 16:38:48 +02:00
|
|
|
|
const admin = await strapi.query('user', 'admin').findOne({ email });
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
|
|
|
|
// admin not found.
|
|
|
|
|
if (!admin) {
|
|
|
|
|
return ctx.badRequest(
|
|
|
|
|
null,
|
2019-12-30 16:24:41 +01:00
|
|
|
|
// FIXME it's not a good security practice to let user know if the email address is registered
|
|
|
|
|
// it'd better to say something like "Email was sent to xyz@xyz.com"
|
|
|
|
|
// this way potential hacker doesn't know if email is registered or not
|
2019-08-21 12:10:23 +02:00
|
|
|
|
formatError({
|
|
|
|
|
id: 'Auth.form.error.user.not-exist',
|
|
|
|
|
message: 'This email does not exit',
|
|
|
|
|
})
|
2019-04-09 12:09:03 +02:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate random token.
|
|
|
|
|
const resetPasswordToken = crypto.randomBytes(64).toString('hex');
|
|
|
|
|
|
|
|
|
|
const settings = {
|
2020-01-11 11:29:24 -05:00
|
|
|
|
object: 'Reset password',
|
2019-04-09 12:09:03 +02:00
|
|
|
|
message: `<p>We heard that you lost your password. Sorry about that!</p>
|
|
|
|
|
|
|
|
|
|
<p>But don’t worry! You can use the following link to reset your password:</p>
|
|
|
|
|
|
|
|
|
|
<p>${url}?code=${resetPasswordToken}</p>
|
|
|
|
|
|
|
|
|
|
<p>Thanks.</p>`,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// Send an email to the admin.
|
|
|
|
|
await strapi.plugins['email'].services.email.send({
|
|
|
|
|
to: admin.email,
|
2020-05-14 11:26:19 +02:00
|
|
|
|
subject: 'Reset password',
|
2019-04-09 12:09:03 +02:00
|
|
|
|
text: settings.message,
|
|
|
|
|
html: settings.message,
|
|
|
|
|
});
|
|
|
|
|
} catch (err) {
|
|
|
|
|
return ctx.badRequest(null, err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update the admin.
|
2020-05-12 16:38:48 +02:00
|
|
|
|
await strapi.query('user', 'admin').update({ id: admin.id }, { resetPasswordToken });
|
2019-04-09 12:09:03 +02:00
|
|
|
|
|
|
|
|
|
ctx.send({ ok: true });
|
|
|
|
|
},
|
|
|
|
|
};
|