0.13.11 : change register template an improve in user extension
Build release Docker image / Build Docker Images (push) Successful in 8m20s
Build release Docker image / Build Docker Images (push) Successful in 8m20s
This commit is contained in:
@@ -7,6 +7,7 @@ ARG NODE_ENV=production
|
|||||||
ENV NODE_ENV=${NODE_ENV}
|
ENV NODE_ENV=${NODE_ENV}
|
||||||
# On les transforme en variables d'environnement pour le processus de build
|
# On les transforme en variables d'environnement pour le processus de build
|
||||||
ENV NODE_ENV=${NODE_ENV}
|
ENV NODE_ENV=${NODE_ENV}
|
||||||
|
ARG URL=https://back.harmonylab.ovh
|
||||||
ENV URL=${URL}
|
ENV URL=${URL}
|
||||||
# Strapi v4/v5 utilise aussi souvent celle-ci pour l'admin
|
# Strapi v4/v5 utilise aussi souvent celle-ci pour l'admin
|
||||||
ENV STRAPI_ADMIN_BACKEND_URL=${URL}
|
ENV STRAPI_ADMIN_BACKEND_URL=${URL}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "harmony-back",
|
"name": "harmony-back",
|
||||||
"version": "0.13.10",
|
"version": "0.13.11",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "A Strapi application",
|
"description": "A Strapi application",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -0,0 +1,222 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Confirmation d'e-mail - ChoralSync</title>
|
||||||
|
<!--[if mso]>
|
||||||
|
<style type="text/css">
|
||||||
|
body,
|
||||||
|
table,
|
||||||
|
td,
|
||||||
|
a {
|
||||||
|
font-family: Arial, Helvetica, sans-serif !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body
|
||||||
|
style="
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background-color: #f9fafb;
|
||||||
|
font-family:
|
||||||
|
"Inter",
|
||||||
|
-apple-system,
|
||||||
|
BlinkMacSystemFont,
|
||||||
|
"Segoe UI",
|
||||||
|
Roboto,
|
||||||
|
Helvetica,
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<table
|
||||||
|
width="100%"
|
||||||
|
border="0"
|
||||||
|
cellspacing="0"
|
||||||
|
cellpadding="0"
|
||||||
|
style="background-color: #f9fafb; padding: 40px 20px"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<!-- Main Container -->
|
||||||
|
<table
|
||||||
|
width="100%"
|
||||||
|
border="0"
|
||||||
|
cellspacing="0"
|
||||||
|
cellpadding="0"
|
||||||
|
style="
|
||||||
|
max-width: 650px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<!-- Header -->
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 32px 32px 16px 32px">
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
ChoralSync
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
font-size: 14px;
|
||||||
|
color: #6b7280;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-top: 4px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
Bienvenue — plus qu’une étape
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 0 32px 32px 32px">
|
||||||
|
<h1
|
||||||
|
style="
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111827;
|
||||||
|
margin-top: 32px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
Bonjour {{USER_NAME}},
|
||||||
|
</h1>
|
||||||
|
<p
|
||||||
|
style="
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #4b5563;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
Merci de t'être inscrit. Clique sur le bouton ci-dessous pour
|
||||||
|
confirmer ton adresse e-mail et activer ton compte.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- CTA Button -->
|
||||||
|
<table
|
||||||
|
border="0"
|
||||||
|
cellspacing="0"
|
||||||
|
cellpadding="0"
|
||||||
|
style="margin-bottom: 40px"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
align="center"
|
||||||
|
bgcolor="#0b1c30"
|
||||||
|
style="border-radius: 12px"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="{{CONFIRM_URL}}"
|
||||||
|
target="_blank"
|
||||||
|
style="
|
||||||
|
display: inline-block;
|
||||||
|
padding: 16px 32px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
Confirmer mon e-mail →
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- Fallback Link -->
|
||||||
|
<div style="margin-top: 32px">
|
||||||
|
<p
|
||||||
|
style="font-size: 14px; color: #6b7280; margin-bottom: 12px"
|
||||||
|
>
|
||||||
|
Si le bouton ne fonctionne pas, copie-colle ce lien dans ton
|
||||||
|
navigateur :
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #f1f5f9;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="{{CONFIRM_URL}}"
|
||||||
|
style="
|
||||||
|
color: #0ea5e9;
|
||||||
|
font-size: 14px;
|
||||||
|
text-decoration: underline;
|
||||||
|
word-break: break-all;
|
||||||
|
font-weight: 500;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{CONFIRM_URL}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 24px 32px; border-top: 1px solid #f1f5f9">
|
||||||
|
<p style="font-size: 14px; color: #9ca3af; margin: 0 0 8px 0">
|
||||||
|
Si tu n'es pas à l'origine de cette inscription, ignore cet
|
||||||
|
e-mail.
|
||||||
|
</p>
|
||||||
|
<p style="font-size: 14px; color: #9ca3af; margin: 0">
|
||||||
|
© ChoralSync 2026 •
|
||||||
|
<a
|
||||||
|
href="https://www.choralsync.com"
|
||||||
|
style="color: #9ca3af; text-decoration: underline"
|
||||||
|
>www.choralsync.com</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- External Footer -->
|
||||||
|
<table
|
||||||
|
width="100%"
|
||||||
|
border="0"
|
||||||
|
cellspacing="0"
|
||||||
|
cellpadding="0"
|
||||||
|
style="max-width: 650px; margin-top: 32px"
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<td align="center" style="font-size: 14px; color: #9ca3af">
|
||||||
|
Besoin d'aide ? Réponds directement à cet e-mail ou consulte
|
||||||
|
notre
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
style="
|
||||||
|
color: #0ea5e9;
|
||||||
|
font-weight: 500;
|
||||||
|
text-decoration: underline;
|
||||||
|
"
|
||||||
|
>centre d'aide</a
|
||||||
|
>.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"name": "Apache 2.0",
|
"name": "Apache 2.0",
|
||||||
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
|
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
|
||||||
},
|
},
|
||||||
"x-generation-date": "2026-05-04T16:37:25.949Z"
|
"x-generation-date": "2026-05-05T11:54:41.084Z"
|
||||||
},
|
},
|
||||||
"x-strapi-config": {
|
"x-strapi-config": {
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
const lod = require("lodash");
|
const lod = require("lodash");
|
||||||
const utils = require("@strapi/utils");
|
const utils = require("@strapi/utils");
|
||||||
const { concat, compact, isArray, toNumber, getOr } = require("lodash/fp");
|
const { toNumber, getOr } = require("lodash/fp");
|
||||||
const cryptoLib = require("crypto");
|
const cryptoLib = require("crypto");
|
||||||
const bcrypt = require("bcryptjs");
|
const bcrypt = require("bcryptjs");
|
||||||
const fs = require("fs").promises;
|
const fs = require("fs").promises;
|
||||||
@@ -9,16 +9,60 @@ const path = require("path");
|
|||||||
|
|
||||||
module.exports = (plugin) => {
|
module.exports = (plugin) => {
|
||||||
const rawProviders = plugin.services.providers({ strapi });
|
const rawProviders = plugin.services.providers({ strapi });
|
||||||
const { ApplicationError, ValidationError, ForbiddenError } = utils.errors;
|
const { ApplicationError, ValidationError } = utils.errors;
|
||||||
const USER_MODEL_UID = "plugin::users-permissions.user";
|
const USER_MODEL_UID = "plugin::users-permissions.user";
|
||||||
|
|
||||||
const sanitizeUser = (user, ctx) => {
|
const sanitizeUser = async (user, ctx) => {
|
||||||
const { auth } = ctx.state;
|
const { auth } = ctx.state;
|
||||||
const userSchema = strapi.getModel("plugin::users-permissions.user");
|
const userSchema = strapi.getModel("plugin::users-permissions.user");
|
||||||
|
|
||||||
return strapi.contentAPI.sanitize.output(user, userSchema, { auth });
|
return strapi.contentAPI.sanitize.output(user, userSchema, { auth });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getUserStats = async (userId) => {
|
||||||
|
const [
|
||||||
|
contactsCount,
|
||||||
|
groupsCount,
|
||||||
|
postsCount,
|
||||||
|
eventsCount,
|
||||||
|
followersCount,
|
||||||
|
followingCount,
|
||||||
|
] = await Promise.all([
|
||||||
|
strapi.db.query("api::contact.contact").count({
|
||||||
|
where: {
|
||||||
|
$or: [{ owner: userId }, { user: userId }],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
strapi.db.query("api::group-membership.group-membership").count({
|
||||||
|
where: {
|
||||||
|
user: userId,
|
||||||
|
role: { $in: ["owner", "member", "admin"] },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
strapi.db.query("api::post-ownership.post-ownership").count({
|
||||||
|
where: { author: userId },
|
||||||
|
}),
|
||||||
|
strapi.db.query("api::event-relationship.event-relationship").count({
|
||||||
|
where: { author: userId },
|
||||||
|
}),
|
||||||
|
strapi.db.query("api::contact.contact").count({
|
||||||
|
where: { user: userId, state: "follow" },
|
||||||
|
}),
|
||||||
|
strapi.db.query("api::contact.contact").count({
|
||||||
|
where: { owner: userId, state: "follow" },
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
contacts: contactsCount,
|
||||||
|
groups: groupsCount,
|
||||||
|
posts: postsCount,
|
||||||
|
events: eventsCount,
|
||||||
|
followers: followersCount,
|
||||||
|
following: followingCount,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const ensureHashedPasswords = async (values) => {
|
const ensureHashedPasswords = async (values) => {
|
||||||
const attributes = strapi.getModel(USER_MODEL_UID).attributes;
|
const attributes = strapi.getModel(USER_MODEL_UID).attributes;
|
||||||
|
|
||||||
@@ -78,7 +122,7 @@ module.exports = (plugin) => {
|
|||||||
to: user.email,
|
to: user.email,
|
||||||
subject: onCreateUser?.subject ?? "Confirme ton adresse e-mail",
|
subject: onCreateUser?.subject ?? "Confirme ton adresse e-mail",
|
||||||
html,
|
html,
|
||||||
from: "ChoralSync <admin@harmonychoral.com>",
|
from: "ChoralSync <contact@choralsync.com>",
|
||||||
});
|
});
|
||||||
|
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
@@ -111,7 +155,7 @@ module.exports = (plugin) => {
|
|||||||
query.access_token || query.code || query.oauth_token;
|
query.access_token || query.code || query.oauth_token;
|
||||||
|
|
||||||
if (!accessToken) {
|
if (!accessToken) {
|
||||||
throw new Error("No access_token.");
|
throw new ApplicationError("No access_token.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const profile = await getProfile(provider, query);
|
const profile = await getProfile(provider, query);
|
||||||
@@ -119,7 +163,7 @@ module.exports = (plugin) => {
|
|||||||
const email = lod.toLower(profile.email);
|
const email = lod.toLower(profile.email);
|
||||||
|
|
||||||
if (!email) {
|
if (!email) {
|
||||||
throw new Error("Email was not available.");
|
throw new ApplicationError("Email was not available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const users = await strapi.db
|
const users = await strapi.db
|
||||||
@@ -142,7 +186,7 @@ module.exports = (plugin) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lod.isEmpty(user) && !advancedSettings.allow_register) {
|
if (lod.isEmpty(user) && !advancedSettings.allow_register) {
|
||||||
throw new Error("Register action is actually not available.");
|
throw new ApplicationError("Register action is actually not available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lod.isEmpty(user)) {
|
if (!lod.isEmpty(user)) {
|
||||||
@@ -150,7 +194,7 @@ module.exports = (plugin) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (users.length && advancedSettings.unique_email) {
|
if (users.length && advancedSettings.unique_email) {
|
||||||
throw new Error("Email is already taken.");
|
throw new ApplicationError("Email is already taken.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultRole = await strapi.db
|
const defaultRole = await strapi.db
|
||||||
@@ -174,8 +218,6 @@ module.exports = (plugin) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const originalMe = plugin.controllers.user.me;
|
|
||||||
|
|
||||||
plugin.controllers.user.me = async (ctx) => {
|
plugin.controllers.user.me = async (ctx) => {
|
||||||
const fullUser = await strapi.db
|
const fullUser = await strapi.db
|
||||||
.query("plugin::users-permissions.user")
|
.query("plugin::users-permissions.user")
|
||||||
@@ -206,58 +248,11 @@ module.exports = (plugin) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = ctx.state.user;
|
const stats = await getUserStats(ctx.state.user.id);
|
||||||
|
|
||||||
const userId = user.id;
|
|
||||||
|
|
||||||
const [
|
|
||||||
contactsCount,
|
|
||||||
groupsCount,
|
|
||||||
postsCount,
|
|
||||||
eventsCount,
|
|
||||||
followersCount,
|
|
||||||
followingCount,
|
|
||||||
] = await Promise.all([
|
|
||||||
strapi.db.query("api::contact.contact").count({
|
|
||||||
where: {
|
|
||||||
$or: [{ owner: userId }, { user: userId }],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
strapi.db.query("api::group-membership.group-membership").count({
|
|
||||||
where: {
|
|
||||||
user: userId,
|
|
||||||
role: { $in: ["owner", "member", "admin"] },
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
strapi.db
|
|
||||||
.query("api::post-ownership.post-ownership")
|
|
||||||
.count({ where: { author: userId } }),
|
|
||||||
strapi.db
|
|
||||||
.query("api::event-relationship.event-relationship")
|
|
||||||
.count({ where: { author: userId } }),
|
|
||||||
strapi.db.query("api::contact.contact").count({
|
|
||||||
where: {
|
|
||||||
user: userId,
|
|
||||||
state: "follow",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
strapi.db.query("api::contact.contact").count({
|
|
||||||
where: {
|
|
||||||
owner: userId,
|
|
||||||
state: "follow",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
const result = {
|
const result = {
|
||||||
...JSON.parse(JSON.stringify(fullUser)),
|
...JSON.parse(JSON.stringify(fullUser)),
|
||||||
stats: {
|
stats,
|
||||||
contacts: contactsCount,
|
|
||||||
groups: groupsCount,
|
|
||||||
posts: postsCount,
|
|
||||||
events: eventsCount,
|
|
||||||
followers: followersCount,
|
|
||||||
following: followingCount,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -279,10 +274,6 @@ module.exports = (plugin) => {
|
|||||||
// 4️⃣ Ajoute un champ calculé
|
// 4️⃣ Ajoute un champ calculé
|
||||||
user.profileCompleted = Boolean(user.username && user.surname);
|
user.profileCompleted = Boolean(user.username && user.surname);
|
||||||
|
|
||||||
// 3️⃣ Supprime les champs sensibles
|
|
||||||
const sensitive = ["password", "resetPasswordToken", "confirmationToken"];
|
|
||||||
sensitive.forEach((key) => delete user[key]); //post_ownerships
|
|
||||||
|
|
||||||
// 5️⃣ Refetch avec relations peuplées
|
// 5️⃣ Refetch avec relations peuplées
|
||||||
try {
|
try {
|
||||||
const populatedUser = await strapi.entityService.findOne(
|
const populatedUser = await strapi.entityService.findOne(
|
||||||
@@ -291,6 +282,7 @@ module.exports = (plugin) => {
|
|||||||
{
|
{
|
||||||
populate: {
|
populate: {
|
||||||
post_ownerships: {
|
post_ownerships: {
|
||||||
|
filters: { contextType: "user", relation: "owner" },
|
||||||
populate: {
|
populate: {
|
||||||
post: {
|
post: {
|
||||||
populate: {
|
populate: {
|
||||||
@@ -300,6 +292,7 @@ module.exports = (plugin) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
contacts: {
|
contacts: {
|
||||||
|
filters: { state: "accepted" },
|
||||||
populate: {
|
populate: {
|
||||||
owner: {
|
owner: {
|
||||||
populate: {
|
populate: {
|
||||||
@@ -314,6 +307,7 @@ module.exports = (plugin) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
group_memberships: {
|
group_memberships: {
|
||||||
|
filters: { role: { $in: ["member", "admin", "owner"] } },
|
||||||
populate: {
|
populate: {
|
||||||
group: {
|
group: {
|
||||||
populate: {
|
populate: {
|
||||||
@@ -326,27 +320,6 @@ module.exports = (plugin) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// Fusionne les données originales (permissions/serialization) avec les relations
|
|
||||||
user = { ...user, ...populatedUser };
|
|
||||||
|
|
||||||
if (user.contacts && Array.isArray(user.contacts)) {
|
|
||||||
user.contacts = user.contacts.filter(
|
|
||||||
(contact) => contact.state === "accepted",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.post_ownerships && Array.isArray(user.post_ownerships)) {
|
|
||||||
user.post_ownerships = user.post_ownerships.filter(
|
|
||||||
(ownership) =>
|
|
||||||
ownership.contextType === "user" && ownership.relation === "owner",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.group_memberships && Array.isArray(user.group_memberships)) {
|
|
||||||
user.group_memberships = user.group_memberships.filter((membership) =>
|
|
||||||
["member", "admin", "owner"].includes(membership.role),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const eventRelationships = await strapi.db
|
const eventRelationships = await strapi.db
|
||||||
.query("api::event-relationship.event-relationship")
|
.query("api::event-relationship.event-relationship")
|
||||||
@@ -356,90 +329,28 @@ module.exports = (plugin) => {
|
|||||||
event: true,
|
event: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
user.event_relationships = eventRelationships || [];
|
|
||||||
const [
|
const stats = await getUserStats(user.id);
|
||||||
contactsCount,
|
|
||||||
groupsCount,
|
const sanitizedPopulatedUser = await sanitizeUser(populatedUser, ctx) as object;
|
||||||
postsCount,
|
|
||||||
eventsCount,
|
// Fusionne les données originales avec les relations sécurisées
|
||||||
followersCount,
|
user = {
|
||||||
followingCount,
|
...user,
|
||||||
] = await Promise.all([
|
...sanitizedPopulatedUser,
|
||||||
strapi.db.query("api::contact.contact").count({
|
event_relationships: eventRelationships || [],
|
||||||
where: {
|
stats
|
||||||
$or: [{ owner: user.id }, { user: user.id }],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
strapi.db.query("api::group-membership.group-membership").count({
|
|
||||||
where: {
|
|
||||||
user: user.id,
|
|
||||||
role: { $in: ["owner", "member", "admin"] },
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
strapi.db
|
|
||||||
.query("api::post-ownership.post-ownership")
|
|
||||||
.count({ where: { author: user.id } }),
|
|
||||||
strapi.db
|
|
||||||
.query("api::event-relationship.event-relationship")
|
|
||||||
.count({ where: { author: user.id } }),
|
|
||||||
strapi.db.query("api::contact.contact").count({
|
|
||||||
where: {
|
|
||||||
user: user.id,
|
|
||||||
state: "follow",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
strapi.db.query("api::contact.contact").count({
|
|
||||||
where: {
|
|
||||||
owner: user.id,
|
|
||||||
state: "follow",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
user.stats = {
|
|
||||||
contacts: contactsCount,
|
|
||||||
groups: groupsCount,
|
|
||||||
posts: postsCount,
|
|
||||||
events: eventsCount,
|
|
||||||
followers: followersCount,
|
|
||||||
following: followingCount,
|
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Erreur populate relations user:", err);
|
console.error("Erreur populate relations user:", err);
|
||||||
// fallback : retourne juste l'utilisateur original
|
// fallback : retourne juste l'utilisateur original
|
||||||
|
user.stats = await getUserStats(user.id);
|
||||||
}
|
}
|
||||||
ctx.body = user;
|
ctx.body = user;
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
const uploadImage = async (
|
// Removed unused uploadImage function
|
||||||
ctx,
|
|
||||||
label: string,
|
|
||||||
username: string,
|
|
||||||
userId: number,
|
|
||||||
) => {
|
|
||||||
const key = `${label}Image`;
|
|
||||||
if (ctx.request.files[key]) {
|
|
||||||
const files = Array.isArray(ctx.request.files[key])
|
|
||||||
? ctx.request.files[key][0]
|
|
||||||
: ctx.request.files[key];
|
|
||||||
const extension = files.originalFilename.match(/\.[0-9a-z]+$/i);
|
|
||||||
const payload = {
|
|
||||||
fileInfo: {
|
|
||||||
caption: "undefined",
|
|
||||||
alternativeText: username || "",
|
|
||||||
name: `${username}_avatar${extension}`,
|
|
||||||
},
|
|
||||||
path: `user/${userId}`,
|
|
||||||
};
|
|
||||||
const asset = await strapi.services["plugin::upload.upload"].upload({
|
|
||||||
data: payload,
|
|
||||||
files,
|
|
||||||
});
|
|
||||||
return asset[0].id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
plugin.services.providers = providers;
|
plugin.services.providers = providers;
|
||||||
|
|
||||||
@@ -450,13 +361,13 @@ module.exports = (plugin) => {
|
|||||||
return ctx.unauthorized();
|
return ctx.unauthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
let data;
|
let data = ctx.request.body.data || ctx.request.body;
|
||||||
if (ctx.request.body.data && typeof ctx.request.body.data === 'string') {
|
if (typeof data === "string") {
|
||||||
data = JSON.parse(ctx.request.body.data);
|
try {
|
||||||
} else if (ctx.request.body.data && typeof ctx.request.body.data === 'object') {
|
data = JSON.parse(data);
|
||||||
data = ctx.request.body.data;
|
} catch (err) {
|
||||||
} else {
|
throw new ValidationError("Invalid JSON format in request body data");
|
||||||
data = ctx.request.body;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newData = lod.pick(data, [
|
const newData = lod.pick(data, [
|
||||||
@@ -557,10 +468,14 @@ module.exports = (plugin) => {
|
|||||||
?.createNotification({
|
?.createNotification({
|
||||||
title: "Bienvenue !",
|
title: "Bienvenue !",
|
||||||
message: `Ton compte est maintenant activé.`,
|
message: `Ton compte est maintenant activé.`,
|
||||||
type: "success",
|
type: "accountCreation",
|
||||||
target_user: result.id,
|
target_user: result.id,
|
||||||
source: "system",
|
source: "system",
|
||||||
payload: { email: result.email },
|
payload: {
|
||||||
|
email: result.email,
|
||||||
|
url: "/app/user",
|
||||||
|
description: "Penses à remplir ton profil",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
strapi.log.info(
|
strapi.log.info(
|
||||||
|
|||||||
Reference in New Issue
Block a user