diff --git a/package.json b/package.json index a751f19..47f681a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "harmony-back", - "version": "0.12.8", + "version": "0.12.9", "private": true, "description": "A Strapi application", "scripts": { diff --git a/src/email-templates/confirmation.html b/src/email-templates/confirmation.html new file mode 100644 index 0000000..aad9309 --- /dev/null +++ b/src/email-templates/confirmation.html @@ -0,0 +1,166 @@ + +Confirme ton adresse e-mail en un clic pour activer ton compte. + + + + + +
+ + + + + + + + + + + + + + + +
+
+ Votre application +
+

+ ChoralSync +

+

+ Bienvenue — plus qu’une étape +

+
+
+
+

+ Bonjour {{USER_NAME}}, +

+

+ Merci de t’être inscrit. Clique sur le bouton ci-dessous pour + confirmer ton adresse e-mail et activer ton compte. +

+ + + + + + +
+ + Confirmer mon e-mail + +
+ + +

+ Si le bouton ne fonctionne pas, copie-colle ce lien dans ton + navigateur : +

+

+ {{CONFIRM_URL}} +

+
+

+ Si tu n’es pas à l’origine de cette inscription, ignore cet + e-mail. +

+

+ © ChoralSync {{YEAR}} • + www.choralsync.com +

+
+ +
+

+ Besoin d’aide ? Réponds directement à cet e-mail ou consulte notre + centre d’aide. +

+
diff --git a/src/extensions/documentation/documentation/1.0.0/full_documentation.json b/src/extensions/documentation/documentation/1.0.0/full_documentation.json index e55b19b..9dedd61 100644 --- a/src/extensions/documentation/documentation/1.0.0/full_documentation.json +++ b/src/extensions/documentation/documentation/1.0.0/full_documentation.json @@ -14,7 +14,7 @@ "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html" }, - "x-generation-date": "2025-11-21T12:49:29.594Z" + "x-generation-date": "2025-11-30T19:50:21.758Z" }, "x-strapi-config": { "plugins": [ diff --git a/src/extensions/users-permissions/strapi-server.ts b/src/extensions/users-permissions/strapi-server.ts index b439474..78bb6b1 100644 --- a/src/extensions/users-permissions/strapi-server.ts +++ b/src/extensions/users-permissions/strapi-server.ts @@ -1,7 +1,75 @@ "use strict"; const lod = require("lodash"); +const utils = require("@strapi/utils"); +const { concat, compact, isArray, toNumber, getOr } = require("lodash/fp"); +const cryptoLib = require("crypto"); +const bcrypt = require("bcryptjs"); + module.exports = (plugin) => { const rawProviders = plugin.services.providers({ strapi }); + const { ApplicationError, ValidationError, ForbiddenError } = utils.errors; + const USER_MODEL_UID = "plugin::users-permissions.user"; + + const sanitizeUser = (user, ctx) => { + const { auth } = ctx.state; + const userSchema = strapi.getModel("plugin::users-permissions.user"); + + return strapi.contentAPI.sanitize.output(user, userSchema, { auth }); + }; + + const ensureHashedPasswords = async (values) => { + const attributes = strapi.getModel(USER_MODEL_UID).attributes; + + for (const key in values) { + if (attributes[key] && attributes[key].type === "password") { + // Check if a custom encryption.rounds has been set on the password attribute + const rounds = toNumber( + getOr(10, "encryption.rounds", attributes[key]) + ); + values[key] = await bcrypt.hash(values[key], rounds); + } + } + values["confirmed"] = false; + return values; + }; + + const edit = async (userId, params = {}) => { + return strapi.db.query(USER_MODEL_UID).update({ + where: { id: userId }, + data: await ensureHashedPasswords(params), + populate: ["role"], + }); + }; + + const sendConfirmationEmail = async (user) => { + // Génération du token de confirmation + + const confirmationToken = cryptoLib.randomBytes(20).toString("hex"); + + await edit(user.id, { confirmationToken }); + const confirmUrl = `${process.env.NEXTJS_URL}/confirmation/submit?confirmation=${confirmationToken}`; + + // Récupération du template HTML défini dans plugins.ts + let html = strapi + .plugin("email") + .config("settings.templates.confirmation.html") as string; + + // Remplacement des variables + html = html + .replace(/{{USER_NAME}}/g, user.username || user.email) + .replace(/{{CONFIRM_URL}}/g, confirmUrl) + .replace(/{{YEAR}}/g, new Date().getFullYear().toString()); + + // Envoi de l'e-mail + await strapi.plugin("email").service("email").send({ + to: user.email, + subject: "Confirme ton adresse e-mail", + html, + from: "ChoralSync ", + }); + + return { ok: true }; + }; const getService = (name) => { return strapi.plugin("users-permissions").service(name); @@ -47,9 +115,13 @@ module.exports = (plugin) => { where: { email }, }); - const advancedSettings = await strapi + const advancedSettings = (await strapi .store({ type: "plugin", name: "users-permissions", key: "advanced" }) - .get(); + .get()) as { + allow_register: boolean; + unique_email?: boolean; + default_role?: string; + }; let user = lod.find(users, { provider }); if (lod.isEmpty(user)) { @@ -453,6 +525,8 @@ module.exports = (plugin) => { activityType: "user" as const, }; + await sendConfirmationEmail(result); + await strapi.entityService.update( "plugin::users-permissions.user", result.id,